Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi access violation inside TLanguages utility

For some reason, trying to create a TLanguages object provided by the SysUtils header by using the singleton or by calling the constructor directly is causing trouble in the wild, where some users report this error (X varies):

Access violation at address X. Write of address X (at address X)

... when the following seemingly innocent line of code is executed:

TLanguages.Create;

To clarify, this is not related to context. I can put this line in any place I like (as the only line of code of an empty program for example), but the problem remains.

The weird part is that this class is part of Delphi's standard headers, which should not fail (right?).

constructor TLanguages.Create;
type
  TCallbackThunk = packed record
    POPEDX: Byte;
    MOVEAX: Byte;
    SelfPtr: Pointer;
    PUSHEAX: Byte;
    PUSHEDX: Byte;
    JMP: Byte;
    JmpOffset: Integer;
  end;
var
  Callback: TCallbackThunk;
begin
  inherited Create;
  Callback.POPEDX := $5A;
  Callback.MOVEAX := $B8;
  Callback.SelfPtr := Self;
  Callback.PUSHEAX := $50;
  Callback.PUSHEDX := $52;
  Callback.JMP     := $E9;
  Callback.JmpOffset := Integer(@TLanguages.LocalesCallback) - Integer(@Callback.JMP) - 5;
  EnumSystemLocales(TFNLocaleEnumProc(@Callback), LCID_SUPPORTED);
end;

The constructor attempts to use a member function as the EnumSystemLocales callback, which seems to be causing the crashes, because copying the TLanguages.LocalesCallback function to global scope and passing that to EnumSystemLocales works perfectly fine.

The struct contains the following Intel x86 assembly, where each item is given by its opcode:

pop  edx
mov  eax Self
push eax
push edx
jmp  JmpOffset

Can anyone explain how the trick works and tell me why it's not working as expected?

like image 235
Orwell Avatar asked Oct 04 '22 13:10

Orwell


1 Answers

It appears to be a known issue with older Delphi versions, related to DEP, as I guessed in comments to the question. It's clear that the code in the RTL cannot work when DEP is enabled.

Here's a link to confirm the theory: http://codecentral.embarcadero.com/Item/23411

Although that CodeCentral article includes code to fix the problem in Delphi 5, it looks like it will work in Delphi 7 too. The fix works by hooking the SysUtils.Languages function. So make sure you always use that rather than calling TLanguages.Create yourself, for obvious reasons.

like image 109
David Heffernan Avatar answered Oct 11 '22 08:10

David Heffernan