Format and pointers / hexadecimal values ​​(memory overwrite)

In my 32-bit Delphi XE2 application (Update 4 Hotfix 1 Version 16.0.4504.48759), I use the Format () routine to register pointer values.

For instance:

Format('MyObject (%p)', [Pointer(MyObject)]); 

However, the resulting string sometimes contains garbage characters (for example, in this case "?" Or "|" instead of hexadecimal digits):

 MyObject (4E?|2010) 

I also get the same result when replacing "% p" with "% x" as follows:

 Format('MyObject (%x)', [Integer(MyObject)]); 

However, using an integer value always works:

 Format('MyObject (%d)', [Integer(MyObject)]); MyObject (1291453120) 

Is there an error that I don’t know about, or could it be due to a problem that occurred here?

Why is the format crashing for anything other than "% s" used with the option?

UPDATE

I accepted Jeroen's answer as it led me to a decision on the troubleshooting process. After the situation with the launch of the application through F7 (in accordance with the comment), I thought that something should happen much earlier in this process. On suspicion, I disabled madExcept from my IDE menu, rebuilt the application, and the problem disappeared. Obviously, no matter which madExcept code was associated with my application, this caused a rewrite in the SysUtils TwoHexLookup constant. Re-enabling madExcept and rebuilding (without any changes on my part) also worked, so there must have been some corruption at the linking stage.

Jerone’s strategy for detecting memory corruption was a useful exercise and should be useful if I came across a similar situation.

+4
source share
2 answers

This seems to be a memory rewrite (compare comment with user1008646 ), you can try the following steps:

Announcement 1: perhaps the easiest way is to view TwoHexLookUp , changing the value of which has the same effect to get the wrong result from s := IntToHex(2129827392, 8); as you observe at runtime.

On Thursday, I am doing work on Delphi at the client, so I might have time to dig a little deeper.

Edit
When you go through your process with F7, you really get into SysInit first.

What you can do there has already set a breakpoint in the TwoHexLookUp array.
Then either F9 / F8 / F7 (depending on the required granularity), and watch the array in the Watch window. That should make you go.

+2
source

My best hypothesis is that your code modifies some memory that it should not, possibly by dereferencing an uninitialized pointer. I created a reproducible case demonstrating this possibility. At least it plays on my machine with my version of the compiler. The exact same code may not do the same in another case.

 procedure TForm1.Button1Click(Sender: TObject); var P : pbyte; S : string; T : ansistring; begin // There nothing special about HexDisplayPrefix. // It just happens to be one of the last global variables // declared in SysUtils. P := @ ( HexDisplayPrefix ); // A few bytes beyond that is TwoHexLookUp. // This is a static array of unicode characters used by the IntToHex routine, // which is in turn used by Format when %p or %x are used. // I'll add an offset to P so that it points into that array. // I'll make the offset odd so that it points to the high byte of a character. // Of course, I can't guarantee that the same offset will work for you P := P + 5763; // Change the lookup table. // Of course, you would never do this on purpose. P ^ := 39; // Now let call IntToHex S := IntToHex ( $E0, 2 ); // Show the value on the screen. // Hey look, the zero has been replaced with a star. memo1 . lines . add ( S ); // Convert the unicode string to an ansistring T := ansistring ( S ); // Show the value on the screen. // When converting to Ansi, the system doesn't know what to do with the star, // so it replaces it with a question mark. memo1 . lines . add ( unicodestring(T) ); end; 

Shows E with star and E with question mark

+4
source

All Articles