Skip to content

Commit aacebbd

Browse files
authored
Fix porting from servicing release (#83633)
1 parent a23cfd3 commit aacebbd

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

src/libraries/System.Private.CoreLib/src/Resources/Strings.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2606,6 +2606,9 @@
26062606
<data name="InvalidProgram_Default" xml:space="preserve">
26072607
<value>Common Language Runtime detected an invalid program.</value>
26082608
</data>
2609+
<data name="InvalidTimeZone_InvalidId" xml:space="preserve">
2610+
<value>The time zone ID '{0}' is invalid.</value>
2611+
</data>
26092612
<data name="InvalidTimeZone_InvalidFileData" xml:space="preserve">
26102613
<value>The time zone ID '{0}' was found on the local computer, but the file at '{1}' was corrupt.</value>
26112614
</data>
@@ -2630,6 +2633,9 @@
26302633
<data name="IO_NoFileTableInInMemoryAssemblies" xml:space="preserve">
26312634
<value>This assembly does not have a file table because it was loaded from memory.</value>
26322635
</data>
2636+
<data name="IO_UnseekableFile" xml:space="preserve">
2637+
<value>Unsupported unseekable file.</value>
2638+
</data>
26332639
<data name="IO_EOF_ReadBeyondEOF" xml:space="preserve">
26342640
<value>Unable to read beyond the end of the stream.</value>
26352641
</data>

src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,55 @@ private static TimeZoneInfo GetLocalTimeZoneCore()
2929
return GetLocalTimeZoneFromTzFile();
3030
}
3131

32+
private static byte[] ReadAllBytesFromSeekableNonZeroSizeFile(string path, int maxFileSize)
33+
{
34+
using FileStream fs = File.OpenRead(path);
35+
if (!fs.CanSeek)
36+
{
37+
throw new IOException(SR.IO_UnseekableFile);
38+
}
39+
40+
if (fs.Length == 0 || fs.Length > maxFileSize)
41+
{
42+
throw new IOException(fs.Length == 0 ? SR.IO_InvalidReadLength : SR.IO_FileTooLong);
43+
}
44+
45+
byte[] bytes = new byte[fs.Length];
46+
fs.ReadExactly(bytes, 0, bytes.Length);
47+
return bytes;
48+
}
49+
50+
// Bitmap covering the ASCII range. The bits is set for the characters [a-z], [A-Z], [0-9], '/', '-', and '_'.
51+
private static byte[] asciiBitmap = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x87, 0xFE, 0xFF, 0xFF, 0x07 };
52+
private static bool IdContainsAnyDisallowedChars(string zoneId)
53+
{
54+
for (int i = 0; i < zoneId.Length; i++)
55+
{
56+
int c = zoneId[i];
57+
if (c > 0x7F)
58+
{
59+
return true;
60+
}
61+
int value = c >> 3;
62+
if ((asciiBitmap[value] & (ulong)(1UL << (c - (value << 3)))) == 0)
63+
{
64+
return true;
65+
}
66+
}
67+
return false;
68+
}
69+
3270
private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachineCore(string id, out TimeZoneInfo? value, out Exception? e)
3371
{
3472
value = null;
3573
e = null;
3674

75+
if (Path.IsPathRooted(id) || IdContainsAnyDisallowedChars(id))
76+
{
77+
e = new TimeZoneNotFoundException(SR.Format(SR.InvalidTimeZone_InvalidId, id));
78+
return TimeZoneInfoResult.TimeZoneNotFoundException;
79+
}
80+
3781
byte[]? rawData=null;
3882
string timeZoneDirectory = GetTimeZoneDirectory();
3983
string timeZoneFilePath = Path.Combine(timeZoneDirectory, id);
@@ -61,7 +105,7 @@ private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachineCore(string id,
61105

62106
try
63107
{
64-
rawData = File.ReadAllBytes(timeZoneFilePath);
108+
rawData = ReadAllBytesFromSeekableNonZeroSizeFile(timeZoneFilePath, maxFileSize: 20 * 1024 * 1024 /* 20 MB */); // timezone files usually less than 1 MB.
65109
}
66110
catch (UnauthorizedAccessException ex)
67111
{
@@ -78,7 +122,7 @@ private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachineCore(string id,
78122
e = ex;
79123
return TimeZoneInfoResult.TimeZoneNotFoundException;
80124
}
81-
catch (IOException ex)
125+
catch (Exception ex) when (ex is IOException || ex is OutOfMemoryException)
82126
{
83127
e = new InvalidTimeZoneException(SR.Format(SR.InvalidTimeZone_InvalidFileData, id, timeZoneFilePath), ex);
84128
return TimeZoneInfoResult.InvalidTimeZoneException;

src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2083,6 +2083,11 @@ public static IEnumerable<object[]> ConvertTime_DateTimeOffset_InvalidDestinatio
20832083
yield return new object[] { s_strPacific + "\\Display" };
20842084
yield return new object[] { s_strPacific + "\n" }; // no trailing newline
20852085
yield return new object[] { new string('a', 100) }; // long string
2086+
yield return new object[] { "/dev/random" };
2087+
yield return new object[] { "Invalid Id" };
2088+
yield return new object[] { "Invalid/Invalid" };
2089+
yield return new object[] { $"./{s_strPacific}" };
2090+
yield return new object[] { $"{s_strPacific}/../{s_strPacific}" };
20862091
}
20872092

20882093
[Theory]

0 commit comments

Comments
 (0)