Răsfoiți Sursa

rtl: check arguments in some TEncoding functions which uses array/string access and raise EEncodingError in case of wrong indexes or string/arrays

git-svn-id: trunk@19387 -
paul 14 ani în urmă
părinte
comite
aa666d38ed

+ 1 - 0
.gitattributes

@@ -10801,6 +10801,7 @@ tests/test/units/sysutils/strtotimetest.pp svneol=native#text/plain
 tests/test/units/sysutils/tastrcmp.pp svneol=native#text/plain
 tests/test/units/sysutils/tastrcmp1.pp svneol=native#text/plain
 tests/test/units/sysutils/tdirex.pp svneol=native#text/plain
+tests/test/units/sysutils/tencodingerrors.pp svneol=native#text/pascal
 tests/test/units/sysutils/tencodingtest.pp svneol=native#text/pascal
 tests/test/units/sysutils/texec1.pp svneol=native#text/plain
 tests/test/units/sysutils/texec2.pp svneol=native#text/plain

+ 4 - 0
rtl/objpas/sysconst.pp

@@ -122,6 +122,10 @@ resourcestring
   SNoToolserver                 = 'Toolserver is not installed, cannot execute Tool';
 
   SNotValidCodePageName         = '%s is not a valid code page name';
+  SInvalidCount                 = 'invalid count [%d]';
+  SCharacterIndexOutOfBounds    = 'character index out of bounds [%d]';
+  SInvalidDestinationArray      = 'invalid destination array';
+  SInvalidDestinationIndex      = 'invalid destination index [%d]';
 
   SNoArrayMatch                 = 'Can''t match any allowed value at pattern position %d, string position %d.';
   SNoCharMatch                  = 'Mismatch char "%s" <> "%s" at pattern position %d, string position %d.';

+ 49 - 4
rtl/objpas/sysutils/sysencoding.inc

@@ -146,6 +146,10 @@ end;
 function TEncoding.GetByteCount(const Chars: TUnicodeCharArray; CharIndex,
   CharCount: Integer): Integer;
 begin
+  if (CharCount < 0) or (Length(Chars) <= CharCount + CharIndex) then
+    raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
+  if (CharIndex < 0) then
+    raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
   Result := GetByteCount(@Chars[CharIndex], CharCount);
 end;
 
@@ -156,6 +160,10 @@ end;
 
 function TEncoding.GetByteCount(const S: UnicodeString; CharIndex, CharCount: Integer): Integer;
 begin
+  if (CharCount < 0) or (Length(S) < CharCount + CharIndex) then
+    raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
+  if (CharIndex < 1) then
+    raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
   Result := GetByteCount(@S[CharIndex], CharCount);
 end;
 
@@ -168,14 +176,29 @@ end;
 function TEncoding.GetBytes(const Chars: TUnicodeCharArray; CharIndex,
   CharCount: Integer): TBytes;
 begin
+  if (CharCount < 0) or (Length(Chars) <= CharCount + CharIndex) then
+    raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
+  if (CharIndex < 0) then
+    raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
   SetLength(Result, GetByteCount(Chars, CharIndex, CharCount));
   GetBytes(@Chars[CharIndex], CharCount, @Result[0], Length(Result));
 end;
 
 function TEncoding.GetBytes(const Chars: TUnicodeCharArray; CharIndex,
   CharCount: Integer; const Bytes: TBytes; ByteIndex: Integer): Integer;
+var
+  ByteLen: Integer;
 begin
-  Result := GetBytes(@Chars[CharIndex], CharCount, @Bytes[ByteIndex], Length(Bytes) - ByteIndex);
+  ByteLen := Length(Bytes);
+  if (ByteLen = 0) and (CharCount > 0) then
+    raise EEncodingError.Create(SInvalidDestinationArray);
+  if (ByteIndex < 0) or (ByteLen < ByteIndex) then
+    raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
+  if (CharCount < 0) or (Length(Chars) <= CharCount + CharIndex) then
+    raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
+  if (CharIndex < 0) then
+    raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
+  Result := GetBytes(@Chars[CharIndex], CharCount, @Bytes[ByteIndex], ByteLen - ByteIndex);
 end;
 
 function TEncoding.GetBytes(const S: UnicodeString): TBytes;
@@ -186,8 +209,19 @@ end;
 
 function TEncoding.GetBytes(const S: UnicodeString; CharIndex, CharCount: Integer;
   const Bytes: TBytes; ByteIndex: Integer): Integer;
+var
+  ByteLen: Integer;
 begin
-  Result := GetBytes(@S[CharIndex], CharCount, @Bytes[ByteIndex], Length(Bytes) - ByteIndex);
+  ByteLen := Length(Bytes);
+  if (ByteLen = 0) and (CharCount > 0) then
+    raise EEncodingError.Create(SInvalidDestinationArray);
+  if (ByteIndex < 0) or (ByteLen < ByteIndex) then
+    raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
+  if (CharCount < 0) or (Length(S) < CharCount + CharIndex) then
+    raise EEncodingError.CreateFmt(SInvalidCount, [CharCount]);
+  if (CharIndex < 1) then
+    raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
+  Result := GetBytes(@S[CharIndex], CharCount, @Bytes[ByteIndex], ByteLen - ByteIndex);
 end;
 
 function TEncoding.GetCharCount(const Bytes: TBytes): Integer;
@@ -198,6 +232,8 @@ end;
 function TEncoding.GetCharCount(const Bytes: TBytes; ByteIndex,
   ByteCount: Integer): Integer;
 begin
+  if (ByteIndex < 0) or (Length(Bytes) < ByteIndex) then
+    raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
   Result := GetCharCount(@Bytes[ByteIndex], ByteCount);
 end;
 
@@ -209,14 +245,23 @@ end;
 
 function TEncoding.GetChars(const Bytes: TBytes; ByteIndex, ByteCount: Integer): TUnicodeCharArray;
 begin
+  if (ByteIndex < 0) or (Length(Bytes) < ByteIndex) then
+    raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
   SetLength(Result, GetCharCount(Bytes, ByteIndex, ByteCount));
   GetChars(@Bytes[ByteIndex], ByteCount, @Result[0], Length(Result));
 end;
 
 function TEncoding.GetChars(const Bytes: TBytes; ByteIndex, ByteCount: Integer;
   const Chars: TUnicodeCharArray; CharIndex: Integer): Integer;
-begin
-  Result := GetChars(@Bytes[ByteIndex], ByteCount, @Chars[CharIndex], Length(Chars) - CharIndex);
+var
+  CharLen: Integer;
+begin
+  if (ByteIndex < 0) or (Length(Bytes) <= ByteIndex) then
+    raise EEncodingError.CreateFmt(SInvalidDestinationIndex, [ByteIndex]);
+  CharLen := Length(Chars);
+  if (CharIndex < 0) or (CharLen <= CharIndex) then
+    raise EEncodingError.CreateFmt(SCharacterIndexOutOfBounds, [CharIndex]);
+  Result := GetChars(@Bytes[ByteIndex], ByteCount, @Chars[CharIndex], CharLen - CharIndex);
 end;
 
 class function TEncoding.GetEncoding(CodePage: Integer): TEncoding;

+ 52 - 0
tests/test/units/sysutils/tencodingerrors.pp

@@ -0,0 +1,52 @@
+program tencodingerrors;
+
+{$mode delphi}{$H+}
+
+uses
+  SysUtils;
+
+var
+  S: String;
+  Bytes: TBytes;
+begin
+  S := '';
+  SetLength(Bytes, 0);
+  try
+    // invalid source array?
+    TEncoding.UTF8.GetBytes(S, 1, -1, Bytes, 0);
+    halt(1);
+  except on E: Exception do
+    WriteLn(E.ClassName, ' ', E.Message);
+  end;
+  S := 'Test';
+  try
+    // delphi raises a message "Invalid source array" while the problem is in
+    // destination array in real
+    TEncoding.UTF8.GetBytes(S, 0, 2, Bytes, 0);
+    halt(2);
+  except on E: Exception do
+    WriteLn(E.ClassName, ' ', E.Message);
+  end;
+  SetLength(Bytes, 1);
+  try
+    // invalid count
+    TEncoding.UTF8.GetBytes(S, 5, 2, Bytes, 0);
+    halt(3);
+  except on E: Exception do
+    WriteLn(E.ClassName, ' ', E.Message);
+  end;
+  try
+    // character index out of bounds
+    TEncoding.UTF8.GetBytes(S, 0, 2, Bytes, 0);
+    halt(4);
+  except on E: Exception do
+    WriteLn(E.ClassName, ' ', E.Message);
+  end;
+  try
+    // invalid destination index
+    TEncoding.UTF8.GetBytes(S, 1, 2, Bytes, -1);
+    halt(5);
+  except on E: Exception do
+    WriteLn(E.ClassName, ' ', E.Message);
+  end;
+end.

+ 1 - 1
tests/test/units/sysutils/tencodingtest.pp

@@ -4,7 +4,7 @@ program tencodingtest;
 {$codepage cp1251}
 
 uses
-  SysUtils, Classes, unit1;
+  SysUtils, Classes;
 
 function CheckCodePage(AFileName: String; AEncoding: TEncoding): Boolean;
 var