From 94f105809a30fbe39b933241e10b64ae337b155c Mon Sep 17 00:00:00 2001 From: BobLd <38405645+BobLd@users.noreply.github.com> Date: Tue, 31 Dec 2024 12:56:38 +0000 Subject: [PATCH] Return a copy of the ArrayPoolBufferWriter buffer in Ascii85, AsciiHex and RunLength filters and fix #964 --- .../Filters/Ascii85FilterTests.cs | 68 +++++++++++++++++-- src/UglyToad.PdfPig/Filters/Ascii85Filter.cs | 4 +- .../Filters/AsciiHexDecodeFilter.cs | 2 +- .../Filters/RunLengthFilter.cs | 2 +- 4 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src/UglyToad.PdfPig.Tests/Filters/Ascii85FilterTests.cs b/src/UglyToad.PdfPig.Tests/Filters/Ascii85FilterTests.cs index 857f01c2c..8e1fba65b 100644 --- a/src/UglyToad.PdfPig.Tests/Filters/Ascii85FilterTests.cs +++ b/src/UglyToad.PdfPig.Tests/Filters/Ascii85FilterTests.cs @@ -22,7 +22,11 @@ public void DecodesWikipediaExample() var result = filter.Decode(bytes, dictionary, 0); - var text = Encoding.ASCII.GetString(result.ToArray()); +#if !NET + string text = Encoding.ASCII.GetString(result.ToArray()); +#else + string text = Encoding.ASCII.GetString(result.Span); +#endif Assert.Equal("Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, " + "that by a perseverance of delight in the continued and indefatigable generation of knowledge, " + @@ -37,7 +41,11 @@ public void ReplacesZWithEmptyBytes() var result = filter.Decode(bytes, dictionary, 1); - var text = Encoding.ASCII.GetString(result.ToArray()); +#if !NET + string text = Encoding.ASCII.GetString(result.ToArray()); +#else + string text = Encoding.ASCII.GetString(result.Span); +#endif Assert.Equal("Man \0\0\0\0is d", text); } @@ -104,8 +112,12 @@ public void DecodesEncodedPdfContent() var result = filter.Decode(Encoding.ASCII.GetBytes(input), dictionary, 0); - var text = Encoding.ASCII.GetString(result.ToArray()); - +#if !NET + string text = Encoding.ASCII.GetString(result.ToArray()); +#else + string text = Encoding.ASCII.GetString(result.Span); +#endif + Assert.Equal(PdfContent.Replace("\r\n", "\n"), text); } @@ -124,11 +136,57 @@ public void DecodesEncodedPdfContentMissingEndOfDataSymbol() var result = filter.Decode(Encoding.ASCII.GetBytes(input), dictionary, 0); - var text = Encoding.ASCII.GetString(result.ToArray()); +#if !NET + string text = Encoding.ASCII.GetString(result.ToArray()); +#else + string text = Encoding.ASCII.GetString(result.Span); +#endif Assert.Equal(PdfContent.Replace("\r\n", "\n"), text); } + [Fact] + public void DecodeParallel() + { + Parallel.For(0, 100_000, i => + { + if (i % 2 == 0) + { + var bytes = Encoding.ASCII.GetBytes("9jqo^zBlbD-"); + + var result = filter.Decode(bytes, dictionary, 1); + +#if !NET + string text = Encoding.ASCII.GetString(result.ToArray()); +#else + string text = Encoding.ASCII.GetString(result.Span); +#endif + + Assert.Equal("Man \0\0\0\0is d", text); + } + else + { + const string input = + @"0d&.mDdmGg4?O`>9P&*SFD)dS2E2gC4pl@QEb/Zr$8N_r$:7]!01IZ=0eskNAdU47<+?7h+B3Ol2_m!C+?)#1+B1 +`9>:0H_br.:""&q8d[6p/M +T()<(%'A;f?Ma+CT;%+E_a:A0>K&EZek1D/aN,F)u&6DBNA*A0>f4BOu4*+EM76E,9eK+B3(_<%9""p.!0AMEb031ATMF#Fp**=$,E,oN2F(oQ1+D#G#De*R""B-;&&FD,T'F!+n3AKY4b +F*22=@:F%a+=SF4C'moi+=Li?EZeh0FD)e-@<>p#@;]TuBl.9kATKCFGA(],AKYo5BOu4*+CT;%+C#7pF_Pr+@VfTuDf0B:+=SF4C'moi+= +Li?EZek1DKKT1F`2DD/TboKAKY](@:s.m/h%oBC'mC/$>""*cF*)G6@;Q?_DIdZpC&~>"; + var result = filter.Decode(Encoding.ASCII.GetBytes(input), dictionary, 0); + +#if !NET + string text = Encoding.ASCII.GetString(result.ToArray()); +#else + string text = Encoding.ASCII.GetString(result.Span); +#endif + + Assert.Equal(PdfContent.Replace("\r\n", "\n"), text); + } + }); + } } } diff --git a/src/UglyToad.PdfPig/Filters/Ascii85Filter.cs b/src/UglyToad.PdfPig/Filters/Ascii85Filter.cs index e5a16240b..5fafa0772 100644 --- a/src/UglyToad.PdfPig/Filters/Ascii85Filter.cs +++ b/src/UglyToad.PdfPig/Filters/Ascii85Filter.cs @@ -29,7 +29,7 @@ public sealed class Ascii85Filter : IFilter /// public ReadOnlyMemory Decode(ReadOnlySpan input, DictionaryToken streamDictionary, int filterIndex) { - var asciiBuffer = new byte[5]; + Span asciiBuffer = stackalloc byte[5]; var index = 0; @@ -96,7 +96,7 @@ public ReadOnlyMemory Decode(ReadOnlySpan input, DictionaryToken str WriteData(asciiBuffer, index, writer); } - return writer.WrittenMemory; + return writer.WrittenMemory.ToArray(); } private static void WriteData(Span ascii, int index, ArrayPoolBufferWriter writer) diff --git a/src/UglyToad.PdfPig/Filters/AsciiHexDecodeFilter.cs b/src/UglyToad.PdfPig/Filters/AsciiHexDecodeFilter.cs index c6558b7f2..d66871dcf 100644 --- a/src/UglyToad.PdfPig/Filters/AsciiHexDecodeFilter.cs +++ b/src/UglyToad.PdfPig/Filters/AsciiHexDecodeFilter.cs @@ -68,7 +68,7 @@ public ReadOnlyMemory Decode(ReadOnlySpan input, DictionaryToken str WriteHexToByte(pair, writer); } - return writer.WrittenMemory; + return writer.WrittenMemory.ToArray(); } private static void WriteHexToByte(ReadOnlySpan hexBytes, ArrayPoolBufferWriter writer) diff --git a/src/UglyToad.PdfPig/Filters/RunLengthFilter.cs b/src/UglyToad.PdfPig/Filters/RunLengthFilter.cs index 1a4d102f0..e345d001f 100644 --- a/src/UglyToad.PdfPig/Filters/RunLengthFilter.cs +++ b/src/UglyToad.PdfPig/Filters/RunLengthFilter.cs @@ -62,7 +62,7 @@ public ReadOnlyMemory Decode(ReadOnlySpan input, DictionaryToken str } } - return output.WrittenMemory; + return output.WrittenMemory.ToArray(); } } } \ No newline at end of file