c.haslam Posted April 30, 2018 Share Posted April 30, 2018 Here is an example: Local $tstruct = DllStructCreate('char[20]') DllStructSetData($tstruct,1,'12345678901234567890') ConsoleWrite('@error='&@error&@CRLF& _ 'DllStructGetData($tstruct,1)='&DllStructGetData($tstruct,1)&@CRLF& _ 'DllStructGetSize($tstruct)='&DllStructGetSize($tstruct)&@CRLF) This writes to the Console: @error=0 DllStructGetData($tstruct,1)=12345678901234567890 DllStructGetSize($tstruct)=20 So it looks to me like the null character at the end of the string is being written just beyond the buffer without @error being set. Thoughts? Spoiler CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard Link to comment Share on other sites More sharing options...
jchd Posted April 30, 2018 Share Posted April 30, 2018 What makes you think that the "string" in struct is appended a Null byte? It isn't technically a "string", it's an array of chars and so there is no need to add any kind of termination because the available size is bounded by it's own declaration. Making the string written there any longer doesn't make a difference: only the first 20 chars are stored (after being converted to ANSI) and retrieved. Local $tstruct = DllStructCreate('char[10]') DllStructSetData($tstruct,1,"I᾽m a kingsize string and will overflow this poor buffer!") ConsoleWrite('@error='&@error&@CRLF& _ 'DllStructGetData($tstruct,1)='&DllStructGetData($tstruct,1)&@CRLF& _ 'DllStructGetSize($tstruct)='&DllStructGetSize($tstruct)&@CRLF) You'll find that the apostrophe becomes a question mark once displayed (even before being stored). That's because I cheated and used the Unicode character ᾽ (U+1FBD = Coronis, an ancient greek character). Since it most probably has no equivalent in your ANSI codepage (well, unless your language setting is "ancient Greek", unlikely to exist) it's converted to ? before storage. That was to illustrate how AutoIt Unicode strings get converted to ANSI char type. Of course if the struct used wchar instead of char this character would have been stored and retrieved verbatim, even if this particular codepoint can't show correctly in the console (use MsgBox to see that Unicode is retained). This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
jpm Posted April 30, 2018 Share Posted April 30, 2018 (edited) as you can see no overflow for @error the doc handle no such case !!! Local $tstruct = DllStructCreate('char[20];char[1]') DllStructSetData($tstruct,2,'x') DllStructSetData($tstruct,1,'1234567890123456789012') ConsoleWrite('@error='&@error&@CRLF& _ 'DllStructGetData($tstruct,1)='&DllStructGetData($tstruct,1)&@CRLF& _ 'DllStructGetSize($tstruct)='&DllStructGetSize($tstruct)&@CRLF) Local $sget = DllStructGetData($tstruct,2) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $sget = ' & $sget & @CRLF & '>Error code: ' & @error & ' Extended code: ' & @extended & ' (0x' & Hex(@extended) & ')' & @CRLF) ;### Debug Console Edited April 30, 2018 by jpm Link to comment Share on other sites More sharing options...
c.haslam Posted April 30, 2018 Author Share Posted April 30, 2018 (edited) Thank you for the comforting words! Here's what led me to think that a terminating null character might be stored: A .jpg from a camera has several dateTime properties. These property items are ASCII and 20 bytes long, but the dateTime value is 19 characters, e.g. 2018:04:30 12:42:34 . So it looked to me as though the writers of the Exif standard might have needed to allow for storing a null character. I have written a script that is a photo viewer/editor with the ability to annotate pictures in Rich Text Format. Its Deskew feature (which is thanks to UEZ) was added several months ago. It uses GDIPlus. It works AOK. But because it de-skews using GDI clones, images (and images saved as jpegs) lose their properties when de-skewed. Recently I have been working on copying Exif data from the image of the picture to the clone. Getting property items is crashing AutoIt. Without getting property items the script never crashes. The only place where the script codes DLLStruct* functions is for Exif properties. The UDFs that handle the properties involve structs. (They are here.) Getting a property item reads a property item stored by GDI as a struct and a sub-struct, and returns a 1-d array, its value element being a 1-d array. Setting a property does the inverse. I am still looking for why AutoIt crashes. Edited April 30, 2018 by c.haslam Spoiler CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard Link to comment Share on other sites More sharing options...
Bilgus Posted May 18, 2018 Share Posted May 18, 2018 If You use a pointer to define a DllStruct You can Sometimes create situations that crash autoit when accessing memory that isn't yours inadvertently.. ;Local $tPtr = Dllstructcreate("ptr", 0) ;AutoIt catches this.. ;Local $tPtr = Dllstructcreate("ptr",0xFFFF0000) ;Crashes x32 & x64 ;Local $tPtr = Dllstructcreate("ptr",0xFFFFFFFF00000000) ;Crashes x64 Local $tPtr = Dllstructcreate("ptr", -1);Crashes All Local $tTest = Dllstructcreate("int;long;ptr;", dllStructGetPtr($tPtr, 1)) DllStructSetData($tTest, 1, 1) DllStructSetData($tTest, 2, 1) Consolewrite(Dllstructgetdata($tTest, 1) & ":" &Dllstructgetdata($tTest, 2) & ":" &Dllstructgetdata($tTest, 3) & ":" & dllStructGetPtr($tTest) & @crlf) Link to comment Share on other sites More sharing options...
jchd Posted May 18, 2018 Share Posted May 18, 2018 This isn't overflowing. In fact this is a rare instance where AutoIt allows use of a pointer. Of course this is a big risk but is necessary in corner cases. This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
Bilgus Posted May 18, 2018 Share Posted May 18, 2018 (edited) I wasn't suggesting this was an overflow, I was just adding a possible reason for what might cause AutoIt to crash as OP observed. Edited May 19, 2018 by Bilgus Link to comment Share on other sites More sharing options...
Bilgus Posted May 19, 2018 Share Posted May 19, 2018 You Could use _WinAPI_IsBadCodePtr() to get some insight into this particular issue Just be aware it should only be used in a debug situation as: It is an obsolete function, Can cause crashes elsewhere, Slows your function down expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Run_Tidy=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <WinAPIMem.au3> ;;_WinAPI_IsBadCodePtr ;;Important This function is obsolete and should not be used. ;;Despite its name, it does not guarantee that the pointer is valid or that the memory pointed to is safe to use. ;;For more information, see Remarks https://msdn.microsoft.com/en-us/library/windows/desktop/aa366713(v=vs.85).aspx ;; Local $tTest Local $tPtr0 = DllStructCreate("ptr", 0) ;AutoIt catches this.. Local $tPtr1 = DllStructCreate("ptr", 0xFFFF0000) ;Crashes x32 & x64 Local $tPtr2 = DllStructCreate("ptr", 0xFFFFFFFF00000000) ;Crashes x64 Local $tPtr3 = DllStructCreate("ptr;", -1) ;Crashes All If _WinAPI_IsBadCodePtr(DllStructGetPtr($tPtr0, 1)) Then If MsgBox($MB_YESNO, "Error Ptr0", "Bad Pointer Skip It?") = $IDNO Then $tTest = DllStructCreate("int;long;ptr;", DllStructGetPtr($tPtr0, 1)) DllStructSetData($tTest, 1, 1) DllStructSetData($tTest, 2, 1) ConsoleWrite(DllStructGetData($tTest, 1) & ":" & DllStructGetData($tTest, 2) & ":" & DllStructGetData($tTest, 3) & ":" & DllStructGetPtr($tTest) & @CRLF) EndIf EndIf If _WinAPI_IsBadCodePtr(DllStructGetPtr($tPtr1, 1)) Then If MsgBox($MB_YESNO, "Error Ptr1", "Bad Pointer Skip It?") = $IDNO Then $tTest = DllStructCreate("int;long;ptr;", DllStructGetPtr($tPtr1, 1)) DllStructSetData($tTest, 1, 1) DllStructSetData($tTest, 2, 1) ConsoleWrite(DllStructGetData($tTest, 1) & ":" & DllStructGetData($tTest, 2) & ":" & DllStructGetData($tTest, 3) & ":" & DllStructGetPtr($tTest) & @CRLF) EndIf EndIf If _WinAPI_IsBadCodePtr(DllStructGetPtr($tPtr2, 1)) Then If MsgBox($MB_YESNO, "Error Ptr2", "Bad Pointer Skip It?") = $IDNO Then $tTest = DllStructCreate("int;long;ptr;", DllStructGetPtr($tPtr2, 1)) DllStructSetData($tTest, 1, 1) DllStructSetData($tTest, 2, 1) ConsoleWrite(DllStructGetData($tTest, 1) & ":" & DllStructGetData($tTest, 2) & ":" & DllStructGetData($tTest, 3) & ":" & DllStructGetPtr($tTest) & @CRLF) EndIf EndIf If _WinAPI_IsBadCodePtr(DllStructGetPtr($tPtr3, 1)) Then If MsgBox($MB_YESNO, "Error Ptr3", "Bad Pointer Skip It?") = $IDNO Then $tTest = DllStructCreate("int;long;ptr;", DllStructGetPtr($tPtr3, 1)) DllStructSetData($tTest, 1, 1) DllStructSetData($tTest, 2, 1) ConsoleWrite(DllStructGetData($tTest, 1) & ":" & DllStructGetData($tTest, 2) & ":" & DllStructGetData($tTest, 3) & ":" & DllStructGetPtr($tTest) & @CRLF) EndIf EndIf Link to comment Share on other sites More sharing options...
c.haslam Posted May 19, 2018 Author Share Posted May 19, 2018 (edited) Thank you for this. It is possible that I have found what is/was causing AutoIt to crash. It seems that a function in GDIPlus.au3, __GDIPlus_ImageGetPropertyItemSize(), is not returning an error code if a property item does not exist in an image, causing the properties to be written to unallocated memory. The code in the standard UDF is: Func __GDIPlus_ImageGetPropertyItemSize($hImage, $iPropID) Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetPropertyItemSize", "handle", $hImage, "uint", $iPropID, "uint*", 0) If @error Then Return SetError(@error, @extended, -1) If $aResult[0] Then Return SetError(10, $aResult[0], -1) Return $aResult[3] EndFunc ;==>__GDIPlus_ImageGetPropertyItemSize My revised code is: Func c__GDIPlus_ImageGetPropertyItemSize($hImage, $iPropID) Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetPropertyItemSize", "handle", $hImage, "uint", $iPropID, "uint*", 0) If $aResult[3]=-1 Then Return SetError(10,$GDIP_ERRPROPERTYNOTFOUND,-1) ; GdipGetPropertyItemSize doesn't set it! EndIf If @error Then Return SetError(@error, @extended, -1) If $aResult[0] Then Return SetError(10, $aResult[0], -1) Return $aResult[3] EndFunc ;==>__GDIPlus_ImageGetPropertyItemSize My suggested change is made here Edited May 19, 2018 by c.haslam Spoiler CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now