Page 1 of 1

Fixed Access Violation when setting Sort Fields in SQLite3 DB

Posted: 11.12.2021, 01:02
by BytePlayer
unit ZDbcCache;

I was getting an access violation when I set the SortIndexFields value to two fields in a table. I tracked it down to the function CompareUnicodeCLob_Asc and discovered it was happening only when it was trying to compare a field with itself. I added an extra check to verify if the two pointers being passed were the same (shown bracketed in {KJS Added} through {KJS END ADD} which seems to solve the problem.

However, it does imply that the sort is not as efficient as it could be as it really shouldn't be comparing two copies of the same field.

Code: Select all

function CompareUnicodeCLob_Asc(const Null1, Null2: Boolean; const V1, V2): Integer;
var
  Blob1, Blob2: IZBlob;
  {$IFDEF MSWINDOWS}
  ValuePtr1, ValuePtr2: Pointer;
  {$ENDIF}
begin
{KJS ADDED}
if (PPointer(V1)^=PPointer(V2)^) then
   begin
      result:=0;
      exit;
   end;
{KJS END ADD}
  Result := NullsCompareMatrix[Null1, Null2];
  if Result = BothNotNull then
  begin
    // Both values not null
    Blob1 := IZBlob(PPointer(V1)^);
    Blob2 := IZBlob(PPointer(V2)^);
    Result := NullsCompareMatrix[(Blob1 = nil) or (Blob1.IsEmpty), (Blob2 = nil) or (Blob2.IsEmpty)];
    if Result <> BothNotNull then Exit;
    if Blob1.IsClob and Blob2.IsClob then
    begin
      {$IFDEF MSWINDOWS}
      ValuePtr1 := Blob1.GetPWideChar;
      ValuePtr2 := Blob2.GetPWideChar;
      SetLastError(0);
        Result := CompareStringW(LOCALE_USER_DEFAULT, 0,
          ValuePtr1, Blob1.Length, ValuePtr2, Blob2.Length) - 2{CSTR_EQUAL};
      end;
      if GetLastError <> 0 then RaiseLastOSError;
      {$ELSE}
        {$IFDEF UNICODE}
        Result := AnsiCompareStr(Blob1.GetUnicodeString, Blob2.GetUnicodeString);
        {$ELSE}
        Result := WideCompareStr(Blob1.GetUnicodeString, Blob2.GetUnicodeString);
        {$ENDIF}
      {$ENDIF}
    end
    else
      Result := ZMemLComp(Blob1.GetBuffer, Blob2.GetBuffer, Max(Blob1.Length, Blob2.Length));
  end;
end;

Re: Fixed Access Violation when setting Sort Fields in SQLite3 DB

Posted: 13.12.2021, 11:44
by marsupilami
Hello BytePlayer,

I am not 100% sure what to make of this.... I don't see immediately where an access violation should happen in the old code. Could you maybe provide a working example? This also helps me in adding a test to the test suites, so we can make sure we don't get that problem again.

Regarding the code:
using "if Blob1.IsClob and Blob2.IsClob then" seems kinda redundant to me because "CompareUnicodeCLob_Asc" should never be used on binary data. Even though SQLite disagrees with us about how to use fields...

Best regards,

Jan