pointersdelphi64-bitdelphi-12-athens

64-bit PChar pointer arithmetic gives range check error


I'm tracing a bug deep in 3rd party code, where the statement

 fStringLen := Str - fToIdent;

gives a run-time error, with:

enter image description here

It's unclear at this moment whether anything Tracing all occurrences it looks like nothing has been done to the fToIndent PChar property (it does not have a setter that I can put a breakpoint on), or if and this is just the initial state after creation of its object.

There is a somewhat older 32-bit version of our software with an older version of the 3rd party software, but where that piece of code is identical. The values are the same if I run the code, but then there is no range check error.

FWIW, this is the code, see last statement :

    function TdaSynHighlighterSQL.HashKey(Str: PChar): Integer;
    // called with Str = 'absolute'

      function GetOrd: Integer;
      begin
        case Str^ of
          '_': Result := 1;
          'a'..'z': Result := 2 + Ord(Str^) - Ord('a');
          'A'..'Z': Result := 2 + Ord(Str^) - Ord('A');
          '@':
            if fDialect in [sqlMSSQL7, sqlMSSQL2K] then
              Result := 24
            else
              Result := 0;
          else Result := 0;
        end;
      end;

    begin
      Result := 0;
      while IsIdentChar(Str^) do  // Always true until Str=''
      begin
        Result := (2 * Result + GetOrd) and $FFFFFF;
        inc(Str);
      end;
      Result := Result and $FF; // 255
      fStringLen := Str - fToIdent;
    end;

How to best fix this?
I find it strange that this code still would not be 64-bit proof


Solution

  • David Heffernan's comment pointed in the right direction:

    fToIdent does not get initialized because the function IdentKind() that sets it was not called yet (not the error).

    In the 32-bit version fStringLen becomes 245556086 if fToIdent=nil and that fits in an integer. In the 64-bit version fStringLen becomes 1513182692840 if fToIdent=nil and that does not fit in the integer.

    We made a quick patch in the source:

    // fStringLen := Str - fToIdent;
    // Prevent rangecheck error
    if (fToIdent=nil) then
      fStringLen := 0
    else
      fStringLen := Str - fToIdent;
     
    

    BTW. This was in ReportBuilder 22.03, in the support forum I got this answer:

    The version of SynEdit used in ReportBuilder has been highly customized and was not originally intended for 64 bit applications. We have converted it to do so however occasionally an issue will arise that slipped through the cracks. There is now a patch available for RB 22.04 that addresses this issue.

    We have not yet updated to 22.04 so I don't know how they patched it.