From 505cf7b443c0f989d1bbe3bf98e79f504c502d47 Mon Sep 17 00:00:00 2001 From: "rosenfield.albert" Date: Fri, 13 Jun 2008 13:54:10 +0000 Subject: [PATCH] Cosmetic: Keep the 'Bytes' variable counting length without the null terminator (shuffle around some +1's). Bugfix: Delphi 2007's Utf8ToUnicode malfunctions and causes an access violation when given a 1-byte UTF8 buffer containing only the null terminator. --- .../zeosdbo/src/dbc/ZDbcMySqlStatement.pas | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas b/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas index d3398da6..414d299a 100644 --- a/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas +++ b/components/zeosdbo/src/dbc/ZDbcMySqlStatement.pas @@ -338,11 +338,11 @@ var begin // UTF-8 strings are at most 4 bytes per character. // Include room for a null terminator. - Bytes := Length(Value) * 4 + 1; - GetMem(Input, Bytes); + Bytes := Length(Value) * 4; + GetMem(Input, Bytes + 1); // Convert WideString input to UTF-8 PChar. - Bytes := UnicodeToUtf8(Input, Bytes, PWideChar(Value), Length(Value)) - 1; + Bytes := UnicodeToUtf8(Input, Bytes + 1, PWideChar(Value), Length(Value)) - 1; // Make room for escaped UTF-8 string. GetMem(Buffer, Bytes * 2 + 1); @@ -355,10 +355,22 @@ begin Bytes := FPlainDriver.GetEscapeString(FHandle, Buffer, Input, Bytes); // Make room for wide version of escaped string. - GetMem(Output, Length(Value) * 4 + 2); + GetMem(Output, Length(Value) * 2 * 2 + 2); + + // There's a big nasty BUG in Utf8ToUnicode: + // ------------------------------------------ + // If it is called with parameters: (2-byte buf), (0 chars), (1-byte buf), (1 byte), + // the function will skip a loop, then decrease an unsigned counter from 0 to 4294967295, + // then use that variable to access the 2-byte buffer way out of bounds. Workaround here: + if Length(Value) = 0 then begin + // Skip Utf8ToUnicode() to avoid bug. + Output[0] := #0; + Output[1] := #0; + end else begin + // Convert back to WideChars, then compose result. + Utf8ToUnicode(Output, Length(Value) * 2, Buffer, Bytes + 1); + end; - // Convert back to WideChars, then compose result. - Utf8ToUnicode(Output, Length(Value) * 2, Buffer, Bytes + 1); Result := '''' + WideString(Output) + ''''; // Free temporary buffers.