Jump to content

Lars Fosdal

Administrators
  • Content Count

    3335
  • Joined

  • Last visited

  • Days Won

    110

Posts posted by Lars Fosdal


  1. Those are not hacks - but techniques.

     

    I try to avoid blocking the window thread when updating the contents, so I usually spin off queries and calculations in a biz.object.

     

    I have a TriggerContentUpdate method that fetches/checks that I have the params I need, sets up the thread and starts it.

    When the thread completes, it triggers a Window redraw which checks if there is data to update from in the biz object, otherwise painting a "No data" or "Processing..." message..

     

    TriggerContentUpdate can then be called from Form.AfterShow, or whenever the parameter data changes, or by timer for automated refresh.


  2. 3 hours ago, Juan C.Cilleruelo said:

     

    Try this: Matlab. 

    From what I read, the 32-bit version of Matlab has issues under W11ARM, while the 64-bit supposedly works.

    IMO - making a general statement that 32-bit and 64-bit intel apps doesn't work on ARM, is a far cry away from specifying some specific apps that don't work.

     

    • Like 1

  3. @Juan C.Cilleruelo

    I've run

    - RAD Studio (32-bit) and Windows apps (32 and 64-bit) made with it 

    - Visual Studio 17.4 (64-bit) and .NET apps made with it.

    - GitKraken (Electron)

    - VS Code (Electron)

    under Windows 11 for ARM in Parallells on my MacBook Pro M1.

     

    Windows 11 for ARM emulates x86 and x64 apps pretty darn good - there is no need to have a native ARM app.

    Considering my projects compiles faster in RAD Studio under Windows 11 for ARM in Parallells under MacOS, than on my one year old Lenovo P16 i7. I am not sure what went wrong for you.

    • Like 1

  4. Spinoff QP entry.

    https://quality.embarcadero.com/browse/RSP-42133

    Warning when a pointer is cast of a different size integer

     

    Consider the following code

    procedure Indata(const InData);
    var
      X: array[0..1] of DWord;
    begin
      x[0]:= PDWord(@InData)^;
      x[1]:= PDWord(LongWord(@InData)+4)^;

    This works well in 32-bit, but when you switch to 64-bit, LongWord is still 32-bit, and and casting a pointer to LongWord will then strip the upper 32-bits of the 64-bit pointer and the PDWord pointer will be wrong;

    Ideally, the compiler should spot when the integer being cast to a pointer is of a different size (32 vs 64) than the integer type and issue a warning.


  5. I decided to test switching one my 32-bit apps to 64-bit, to see how it would behave. It uses an encryption algorithm called TwoFish from an old encryption lib - DCPCrypt2 by David Barton- which seems to no longer be maintained, and to my dismay, the encryption failed with a access violation. 

     

    Project ConsoleTest.exe raised exception class $C0000005 with message ‘c0000005 ACCESS_VIOLATION’.

     

    that was eaten by an exception handler in the lib - which presented a different error message

    EDCP_cipher: Unable to allocate sufficient memory for hash digest

     

    It fails on the first half of this expression in the code below;

    x[1]:= PDWord(longword(@InData)+4)^ xor SubKeys[INPUTWHITEN+1];
    i.e. PDWord(longword(@InData)+4)^

     

    Question: Longwords and DWords are supposedly the same in both 32-bit and 64-bit, so why does the pointer arithmetic fail in 64-bit?

     

     

    Below is the original method that works well in 32-bit, but blows up in 64-bit.
    In the DCPtwofish.pas unit:

    procedure TDCP_twofish.EncryptECB(const InData; var OutData);
    var
      i: longword;
      t0, t1: DWord;
      X: array[0..3] of DWord;
    begin
      if not fInitialized then
        raise EDCP_blockcipher.Create('Cipher not initialized');
      x[0]:= PDWord(@InData)^ xor SubKeys[INPUTWHITEN];
      x[1]:= PDWord(longword(@InData)+4)^ xor SubKeys[INPUTWHITEN+1]; // <- 64-bit Access Violation!
      x[2]:= PDWord(longword(@InData)+8)^ xor SubKeys[INPUTWHITEN+2]; 
      x[3]:= PDWord(longword(@InData)+12)^ xor SubKeys[INPUTWHITEN+3];
      i:= 0;
      while i<= NUMROUNDS-2 do
      begin
        t0:= sBox[0,(x[0] shl 1) and $1fe] xor sBox[0,((x[0] shr 7) and $1fe)+1]
          xor sBox[2,(x[0] shr 15) and $1fe] xor sBox[2,((x[0] shr 23) and $1fe)+1];
        t1:= sBox[0,((x[1] shr 23) and $1fe)] xor sBox[0,((x[1] shl 1) and $1fe)+1]
          xor sBox[2,((x[1] shr 7) and $1fe)] xor sBox[2,((x[1] shr 15) and $1fe)+1];
        x[3]:= (x[3] shl 1) or (x[3] shr 31);
        x[2]:= x[2] xor (t0 +   t1 + SubKeys[ROUNDSUBKEYS+2*i]);
        x[3]:= x[3] xor (t0 + 2*t1 + SubKeys[ROUNDSUBKEYS+2*i+1]);
        x[2]:= (x[2] shr 1) or (x[2] shl 31);
    
        t0:= sBox[0,(x[2] shl 1) and $1fe] xor sBox[0,((x[2] shr 7) and $1fe)+1]
          xor sBox[2,((x[2] shr 15) and $1fe)] xor sBox[2,((x[2] shr 23) and $1fe)+1];
        t1:= sBox[0,((x[3] shr 23) and $1fe)] xor sBox[0,((x[3] shl 1) and $1fe)+1]
          xor sBox[2,((x[3] shr 7) and $1fe)] xor sBox[2,((x[3] shr 15) and $1fe)+1];
        x[1]:= (x[1] shl 1) or (x[1] shr 31);
        x[0]:= x[0] xor (t0 +   t1 + SubKeys[ROUNDSUBKEYS+2*(i+1)]);
        x[1]:= x[1] xor (t0 + 2*t1 + SubKeys[ROUNDSUBKEYS+2*(i+1)+1]);
        x[0]:= (x[0] shr 1) or (x[0] shl 31);
        Inc(i,2);
      end;
      PDWord(longword(@OutData)+ 0)^:= x[2] xor SubKeys[OUTPUTWHITEN];
      PDWord(longword(@OutData)+ 4)^:= x[3] xor SubKeys[OUTPUTWHITEN+1];
      PDWord(longword(@OutData)+ 8)^:= x[0] xor SubKeys[OUTPUTWHITEN+2];
      PDWord(longword(@OutData)+12)^:= x[1] xor SubKeys[OUTPUTWHITEN+3];
    end;

     

    The answer came from a fellow developer elsewhere:

    It fails because pointers are not longwords in 64 bit and casting to longword clips the upper 32 bits, so the cast of a pointer to a longword is not the way to do it.

    Instead - the correct way would be to change the expression to PDWord(UIntPtr(@InData)+4)^

     

    After some fiddling in the debugger, I thought - why not try a cleaner approach to the pointer casts, and this is what I came up with - and it works as intended in both 32-bit and 64-bit, without the explicit offset calculations.  

    type
      ArrDWord = array[0..3] of DWord;
      pArrDWord = ^ArrDWord;
    
    procedure TDCP_twofish.EncryptECB(const InData; var OutData);
    var
      i: longword;
      t0, t1: DWord;
      X: array[0..3] of DWord;
    begin
      if not fInitialized then
        raise EDCP_blockcipher.Create('Cipher not initialized');
      x[0]:= PArrDWord(@InData)[0] xor SubKeys[INPUTWHITEN];
      x[1]:= PArrDWord(@InData)[1] xor SubKeys[INPUTWHITEN+1];
      x[2]:= PArrDWord(@InData)[2] xor SubKeys[INPUTWHITEN+2];
      x[3]:= PArrDWord(@InData)[3] xor SubKeys[INPUTWHITEN+3];
      i:= 0;
      while i<= NUMROUNDS-2 do
      begin
        t0:= sBox[0,(x[0] shl 1) and $1fe] xor sBox[0,((x[0] shr 7) and $1fe)+1]
          xor sBox[2,(x[0] shr 15) and $1fe] xor sBox[2,((x[0] shr 23) and $1fe)+1];
        t1:= sBox[0,((x[1] shr 23) and $1fe)] xor sBox[0,((x[1] shl 1) and $1fe)+1]
          xor sBox[2,((x[1] shr 7) and $1fe)] xor sBox[2,((x[1] shr 15) and $1fe)+1];
        x[3]:= (x[3] shl 1) or (x[3] shr 31);
        x[2]:= x[2] xor (t0 +   t1 + SubKeys[ROUNDSUBKEYS+2*i]);
        x[3]:= x[3] xor (t0 + 2*t1 + SubKeys[ROUNDSUBKEYS+2*i+1]);
        x[2]:= (x[2] shr 1) or (x[2] shl 31);
    
        t0:= sBox[0,(x[2] shl 1) and $1fe] xor sBox[0,((x[2] shr 7) and $1fe)+1]
          xor sBox[2,((x[2] shr 15) and $1fe)] xor sBox[2,((x[2] shr 23) and $1fe)+1];
        t1:= sBox[0,((x[3] shr 23) and $1fe)] xor sBox[0,((x[3] shl 1) and $1fe)+1]
          xor sBox[2,((x[3] shr 7) and $1fe)] xor sBox[2,((x[3] shr 15) and $1fe)+1];
        x[1]:= (x[1] shl 1) or (x[1] shr 31);
        x[0]:= x[0] xor (t0 +   t1 + SubKeys[ROUNDSUBKEYS+2*(i+1)]);
        x[1]:= x[1] xor (t0 + 2*t1 + SubKeys[ROUNDSUBKEYS+2*(i+1)+1]);
        x[0]:= (x[0] shr 1) or (x[0] shl 31);
        Inc(i,2);
      end;
      PArrDWord(@OutData)[0] := x[2] xor SubKeys[OUTPUTWHITEN];
      PArrDWord(@OutData)[1] := x[3] xor SubKeys[OUTPUTWHITEN+1];
      PArrDWord(@OutData)[2] := x[0] xor SubKeys[OUTPUTWHITEN+2];
      PArrDWord(@OutData)[3] := x[1] xor SubKeys[OUTPUTWHITEN+3];
    end;

    Here is the test code:

    uses
      DCPtwofish, DCPsha1;
    
    const
      CRYPT_KEY = 'TheVØryBÆDSecretStr.ing';
    
    function EncryptTwofish(const s: string; Key: string = CRYPT_KEY) : string;
    var
      Cipher : TDCP_twofish;
    begin
      Result:='';
      Cipher := TDCP_twofish.Create(nil);
      try
          Cipher.InitStr(AnsiString(Key), TDCP_sha1);
          Result := string(Cipher.EncryptString(AnsiString(s)));
      finally
        Cipher.Free;
      end;
    end;
    
    procedure TestEncrypt;
    begin
      Writeln(EncryptTwoFish('Keep this text a secret'));
    end;

     

    • Like 1

  6. Have any of you used this old lib in 64-bit? It works fine in 32-bit, but I get

    Project MyProject.exe raised exception class EDCP_cipher with message 'Unable to allocate sufficient memory for hash digest'.

    when running as 64-bit.

     

    Curious to know if anyone has worked around this issue already.

×