[SOLVED] Attempt to dereference a generic pointer on Linux but not on Windows lazarus / 32-Linux ---------------------------------------------------------------------- Gizmo · 2021-05-20 10:33 Folks Last night I was up into the early hours trying to debug a mysterious issue. I am using a fantastic well established C library in one of my projects using Lazarus 2.0.12 and FPC 3.2.0. One of the function calls of that library has the following C based declaration : (https://github.com/libyal/libewf-legacy/blob/d35048cd97d2e192708988fc 1424cd2ca2a00e76/include/libewf.h.in#L1589) Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i int libewf_handle_get_utf8_hash_value(     libewf_handle_t *handle,     const uint8_t *identifier,     size_t identifier_length,     uint8_t *utf8_string,     size_t utf8_string_size,     libewf_error_t **error ); So it expects something like : Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i libewf_handle_get_utf8_hash_value( handle, (uint8_t *) "MD5", 3, value, value_size, error )(https://github.com/libyal/libewf- legacy/blob/main/libewf/libewf_metadata.c#L5084) My implementation (which has only been slightly updated over the years from the original author of the wrapper) works flawlessly...on Windows. As follows : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function TLibEWF.libewf_GetHashValue(identifier:ansistring;var value:ansistring) : integer;var  err:pointer;  p:pansichar;  l:tsize;begin  err:=nil;  Result:=-1;  if fLibHandle<>0 then  begin  //if LIBEWF_VERSION='V1' then ...;  getmem(p,255);  if LIBEWF_VERSION='V2' then   Result:=flibewfhandlegetutf8hashvalue(fCurEWFHandle,   // Holds the handle address of the file                                          pansichar(identifier),  // identifier shows 'MD5'                                        length(identifier),       // returns 3                                        p,                             // Holds the string of the hash itself                                        l,                              // Holds the digit 1                                        @err);                      // Nothing  if result=1 then value:=strpas(p);                      // Result does equal 1, and value now equals hash string  FreeMemory(p);  end;end;     On Linux, however, everything is the same except p and l and err. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i p = pchar($00007FFFEDA33C20) #152'7'#163#237#255#127, (p)^ = 152 #152l = 3902020624err = (err)^ = Attempt to dereference a generic pointer.  I've asked the developer of the library who suspects there to be some issue between the interfacing of Pascal and the library and a parameter of the function call that might have a different bit size in Pascal then the library expects? Can anyone see where I am going wrong here? Or who could explain why it works perfectly on Windows returning 1, but returns -1 on Linux? ---------------------------------------------------------------------- MarkMLl · 2021-05-20 10:47 Are you sure that the problem's where you think it is? The reason I ask is this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i begin  //if LIBEWF_VERSION='V1' then ...;  getmem(p,255);  if LIBEWF_VERSION='V2' then  if your ... means that you've actually got v1-specific code in there then since the version check is being done at runtime then you're actually trying to compile both the v1- and v2-specific calls. You need something like Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$define LIBEWF_VERSION_V2 } {$ifndef LIBEWF_VERSION_V2 }...{$else }...{$endif LIBEWF_VERSION_V2 }  MarkMLl ---------------------------------------------------------------------- PascalDragon · 2021-05-20 11:16 Quote from: Gizmo on May 20, 2021, 12:33:26 pmCan anyone see where I am going wrong here? Or who could explain why it works perfectly on Windows returning 1, but returns -1 on Linux? How is the flibewfhandlegetutf8hashvalue declared? ---------------------------------------------------------------------- Gizmo · 2021-05-20 12:02 Here are the declaration areas that I think are relevant. Hopefully it helps you help me? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type TINT16 = ShortInt; // was short  TUINT16 = word;  TUINT8 = byte;  PLIBEWFHDL = pointer;  TSIZE = longword;  TSIZE64 = int64;  PSIZE64 = ^int64;  TARRPCHAR = array of pansiChar;  PARRPCHAR = ^TARRPCHAR;    ... Tlibewfhandlegetutf8hashvalue     = function(handle : PLIBEWFHDL;identifier:pansichar; identifier_length:TSIZE; utf8_string:pansichar; utf8_string_length:TSIZE; error:pointer) : integer; cdecl; ...TLibEWF = class(TObject)  private                ...  public     function libewf_GetHashValue(identifier:ansistring;var value:ansistring) : integer;  constructor TLibEWF.create();     if fLibHandle<>nilhandle then  ... @flibewfhandlegetutf8hashvalue     :=GetProcAddress(fLibHandle,'libewf_handle_get_utf8_hash_value');... Mark - thanks for your comment though there is actually nothing after that V1 thing. It just forgot to strip it out. ---------------------------------------------------------------------- Zvoni · 2021-05-20 13:12 Errrr..... the last parameter is a Pointer to Pointer according to the c-declaration in the first post What's the underlying datatype of libewf_error_t? Fixed-size integer or something? like an error code? Usually a Pointer to pointer is an array in c Have you tried casting it to the correct type before dereferencing it? IIRC, you cannot dereference a "raw" pointer ---------------------------------------------------------------------- Gizmo · 2021-05-20 13:42 Zvoni - I am struggling to find what error actually is. Nearest I can find is this : https://github.com/libyal/libewf- legacy/blob/main/libewf/libewf_error.h On the "pointer to pointer" point, my understanding, which may be wrong, is I have a var called err that is declared as a pointer : err : pointer And then in the call I use @err which means "point to the pointer for error". Is that not correct? (though, AFAIK, its not the error return that is the problem) ---------------------------------------------------------------------- Zvoni · 2021-05-20 14:24 Line 29 https://bitbucket.ki.agh.edu.pl/projects/FSLIB/repos/libewf/browse/inc lude/libewf/error.h It's a TypeDef for IntPtr_t --> Pointer to Fixed Size Integer? You could try dereferencing it this way: Writeln(PInteger(err)^); Or just declare err as PInteger EDIT: If that IntPtr_t is already a Pointer to Integer, wouldn't that mean you actually have to pass a Pointer To Pointer To Pointer as the third argument? Type already a pointer plus twice '**' In that case it would mean that err is a PPInteger EDIT2: What is actually your error-message you get on Linux (from the compiler?) ---------------------------------------------------------------------- Gizmo · 2021-05-20 14:56 I tried switching err to PInteger. But the return result is still -1 (on Linux). As PInteger, debugger reports : err = $000000000155F3F0 (err)^ = Attempt to dereference a generic pointer. As Pointer, debugger reports : err = $00000000015D8CD0 (err)^ = Attempt to dereference a generic pointer. This is also stated in original post for info. Either way, the point here is the code works on Windows. But it doesn't on Linux, or rather, it runs on Linux but doesn't return values on Linux that it should, and does, on Windows. The err var is not the problem, I don't believe. The problem is that var p and l are having values put in them that are invalid...on Linux. But perfectly fine, on Windows. Using the libraries error reporting code I was able to generate this message data : Code: [Select]libuna_unicode_character_copy_to_utf8: UTF-8 string too small. libuna_utf8_string_with_index_copy_from_utf8_stream: unable to copy Unicode character to UTF-8. libfvalue_string_copy_to_utf8_string_with_index: unable to copy UTF-8 stream to UTF-8 string. libfvalue_value_copy_to_utf8_string_with_index: unable to copy instance to UTF-8 string. libfvalue_value_copy_to_utf8_string: unable to copy value: 0 to UTF-8 string. libewf_handle_get_utf8_hash_value: unable to copy hash value to UTF-8 string. which, given that p is complaining about being unable to be dereferenced, and l is a massive longword value instead of just 1, makes a degree of sense. I still don't see where the problem is, though, IRO Linux itself. ---------------------------------------------------------------------- Zvoni · 2021-05-20 16:42 What‘s the Longword has to do with your error-message? I‘d rather look at your PAnsichar ---------------------------------------------------------------------- tetrastes · 2021-05-21 08:00 Quote from: Gizmo on May 20, 2021, 02:02:39 pmHere are the declaration areas that I think are relevant. Hopefully it helps you help me? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type TINT16 = ShortInt; // was short...   TSIZE = longword; ... Tlibewfhandlegetutf8hashvalue     = function(handle : PLIBEWFHDL;identifier:pansichar; identifier_length:TSIZE; utf8_string:pansichar; utf8_string_length:TSIZE; error:pointer) : integer; cdecl; .... What is the bitness at Linux and Windows? Your TSIZE (used for size_t in C) is for 32 bit. At 64-bit systems size_t is 64 bit. Also note that your TINT16 is 8-bit, is it intentionally? ---------------------------------------------------------------------- Gizmo · 2021-05-22 14:46 Zvoni That PAnsiChar was certainly the culprit. After several more days of wrestling, I went to the developer of the library directly who very kindly, and simply, and almost immediately pointed out that all I had to do was change the p variable to string! So Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  p :stringbegin  SetLength(p, 512);  l := 512...end;  and it then works. The explanation being that Linux Unicode (wchar_t) strings are typically UTF-32 and on Windows UTF-16 little-endian. Since UTF-8 is typically a narrow string (char) he opts to treat these strings a byte strings/raw buffers (no encoding). And as they dont contain non ASCII chars in themselves, a normal string suffices in FPC. Only a week of my life spent wrestling with that, and what an utter fool I feel like now. But hey ho. Solved. Thanks for all the help guys.