Skip to content

Commit 64c2d60

Browse files
committed
Throw ParseException on out of range in UTF8toUTF16, add more tests
1 parent f33e0c9 commit 64c2d60

2 files changed

Lines changed: 40 additions & 4 deletions

File tree

src/Lucene.Net.Tests/Util/TestUnicodeUtil.cs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,29 @@ public virtual void TestUTF8UTF16CharsRef()
327327
}
328328
}
329329

330+
[Test]
331+
[LuceneNetSpecific]
332+
[TestCase(new byte[] { 0x63, 0x61, 0xc3 }, true)] // ca�, start of 2-byte sequence
333+
[TestCase(new byte[] { 0x63, 0x61, 0xe3 }, true)] // ca�, start of 3-byte sequence
334+
[TestCase(new byte[] { 0x63, 0x61, 0xf3 }, true)] // ca�, start of 4-byte sequence
335+
[TestCase(new byte[] { 0x63, 0x61, 0xc3, 0xb1, 0x6f, 0x6e }, false)] // cañon
336+
public void TestUTF8toUTF16Exception(byte[] invalidUtf8, bool shouldThrow)
337+
{
338+
var scratch = new CharsRef();
339+
340+
if (shouldThrow)
341+
{
342+
Assert.Throws<ParseException>(() => UnicodeUtil.UTF8toUTF16(invalidUtf8, scratch));
343+
}
344+
else
345+
{
346+
UnicodeUtil.UTF8toUTF16(invalidUtf8, scratch);
347+
}
348+
}
349+
330350
[Test]
331351
[LuceneNetSpecific] // this is a Lucene.NET specific method
352+
[Repeat(100)]
332353
public void TestTryUTF8toUTF16()
333354
{
334355
string unicode = TestUtil.RandomRealisticUnicodeString(Random);
@@ -342,14 +363,17 @@ public void TestTryUTF8toUTF16()
342363

343364
[Test]
344365
[LuceneNetSpecific] // this is a Lucene.NET specific method
345-
public void TestUTF8toUTF16WithFallback()
366+
[TestCase(new byte[] { 0x63, 0x61, 0xc3 }, "ca\ufffd")] // ca�, start of 2-byte sequence
367+
[TestCase(new byte[] { 0x63, 0x61, 0xe3 }, "ca\ufffd")] // ca�, start of 3-byte sequence
368+
[TestCase(new byte[] { 0x63, 0x61, 0xf3 }, "ca\ufffd")] // ca�, start of 4-byte sequence
369+
[TestCase(new byte[] { 0x63, 0x61, 0xc3, 0xb1, 0x6f, 0x6e }, "cañon")]
370+
public void TestUTF8toUTF16WithFallback(byte[] utf8, string expected)
346371
{
347-
byte[] invalidUtf8 = { 0x63, 0xc3 }; // Invalid ending UTF-8 sequence
348372
var scratch = new CharsRef();
349373

350-
UnicodeUtil.UTF8toUTF16WithFallback(invalidUtf8, scratch);
374+
UnicodeUtil.UTF8toUTF16WithFallback(utf8, scratch);
351375

352-
Assert.AreEqual("c\ufffd", scratch.ToString());
376+
Assert.AreEqual(expected, scratch.ToString());
353377
}
354378
}
355379
}

src/Lucene.Net/Util/UnicodeUtil.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,15 +925,27 @@ public static void UTF8toUTF16(ReadOnlySpan<byte> utf8, CharsRef chars)
925925
}
926926
else if (b < 0xe0)
927927
{
928+
if (utf8.Length <= i)
929+
{
930+
throw new ParseException($"Invalid UTF-8 starting at [{b:x2}] at offset {i - 1}", i - 1);
931+
}
928932
@out[out_offset++] = (char)(((b & 0x1f) << 6) + (utf8[i++] & 0x3f));
929933
}
930934
else if (b < 0xf0)
931935
{
936+
if (utf8.Length <= i + 1)
937+
{
938+
throw new ParseException($"Invalid UTF-8 starting at [{b:x2}] at offset {i - 1}", i - 1);
939+
}
932940
@out[out_offset++] = (char)(((b & 0xf) << 12) + ((utf8[i] & 0x3f) << 6) + (utf8[i + 1] & 0x3f));
933941
i += 2;
934942
}
935943
else
936944
{
945+
if (utf8.Length <= i + 2)
946+
{
947+
throw new ParseException($"Invalid UTF-8 starting at [{b:x2}] at offset {i - 1}", i - 1);
948+
}
937949
if (Debugging.AssertsEnabled) Debugging.Assert(b < 0xf8, "b = 0x{0:x}", b);
938950
int ch = ((b & 0x7) << 18) + ((utf8[i] & 0x3f) << 12) + ((utf8[i + 1] & 0x3f) << 6) + (utf8[i + 2] & 0x3f);
939951
i += 3;

0 commit comments

Comments
 (0)