Page 1 of 1

MSSQL + Problem with StringReplace function for #0

Posted: 15.11.2014, 13:45
by ChrisCross
In unit ZDbcDbLibUtils.pas is used to replace #0 in string format for
"stAsciiStream, stUnicodeStream, stBinaryStream:" with ''.
The Delphi StringReplace function (at least Delphi 7 or Delphi XE2 one) uses AnsiPos and later StrPosLen witch ignores the #0 character so the replacement does not work resulting in unterminated string.
The isue was also presented in http://zeosbugs.firmos.at/view.php?id=267.

Code: Select all

StringReplace(GetValidatedAnsiStringFromBuffer(TempBlob.GetBuffer, TempBlob.Length, ConSettings, zCP_UTF8), #0, '', [rfReplaceAll]), '''')
.

For solving this issue we have to replace then AnsiPos with PosEx function.
So I included in ZSysUtils a copy of StringReplace function for both AnsiString and String and replace the AnsiPos with PosEx.

Code: Select all

function StringReplace(const S, OldPattern, NewPattern: AnsiString;
  Flags: TReplaceFlags): AnsiString;
var
  SearchStr, Patt, NewStr: AnsiString;
  Offset: Integer;
begin
  if rfIgnoreCase in Flags then
  begin
    SearchStr := AnsiUpperCase(S);
    Patt := AnsiUpperCase(OldPattern);
  end else
  begin
    SearchStr := S;
    Patt := OldPattern;
  end;
  NewStr := S;
  Result := '';
  while SearchStr <> '' do
  begin
    Offset := [b]AnsiStrings.PosEx(Patt, SearchStr);[/b]
    if Offset = 0 then
    begin
      Result := Result + NewStr;
      Break;
    end;
    Result := Result + Copy(NewStr, 1, Offset - 1) + NewPattern;
    NewStr := Copy(NewStr, Offset + Length(OldPattern), MaxInt);
    if not (rfReplaceAll in Flags) then
    begin
      Result := Result + NewStr;
      Break;
    end;
    SearchStr := Copy(SearchStr, Offset + Length(Patt), MaxInt);
  end;
end;
Then I replaced all the implication of StringReplace focusing on ZDbcDbLibUtils.pas and ZDbcPostgreSqlUtils.pas where was replacement of #0.
Then all the references of StringReplace in all ZeosDBO sources.

Re: MSSQL + Problem with StringReplace function for #0

Posted: 15.11.2014, 13:48
by ChrisCross
The issue is happening also when using varchar columns or varbinary columns and using db editors for rtf ( Rich text format).

Re: MSSQL + Problem with StringReplace function for #0

Posted: 16.11.2014, 19:08
by EgonHugeist
Grumble,

i'm affraid. I didn't know that StringReplace isn't able to play with #0 bytes.

Note: PosEx is buggy on Delphi 7 and produces memory-leaks. That's why i do not use PosEx currently. Instead of i did patch Pos() inside all Zeos code for max performance of 7.2.

In addition to your patch i need to add PosEx for D7. Have to check the FastCode-Project since which version PosEx really is introduced in Delphi. So stay tuned i'll apply your suggestions next days including a PosEx replacement..