mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-11-24 08:47:01 +08:00
Prevent RunLengthFilter malicious OOM
This commit is contained in:
@@ -7,6 +7,18 @@
|
||||
|
||||
public class GithubIssuesTests
|
||||
{
|
||||
[Fact]
|
||||
public void Issue1067()
|
||||
{
|
||||
var path = IntegrationHelpers.GetSpecificTestDocumentPath("GHOSTSCRIPT-691770-0.pdf");
|
||||
|
||||
using (var document = PdfDocument.Open(path, new ParsingOptions() { UseLenientParsing = true }))
|
||||
{
|
||||
var ex = Assert.Throws<PdfDocumentFormatException>(() => document.GetPage(1));
|
||||
Assert.StartsWith("Decoded stream size exceeds the estimated maximum size.", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Issue1054()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
%PDF-1.1
|
||||
|
||||
1 0 obj
|
||||
<<
|
||||
/Type /Catalog
|
||||
/Outlines 2 0 R
|
||||
/Pages 3 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<<
|
||||
/Type /Outlines
|
||||
/Count 0
|
||||
>>
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<<
|
||||
/Type /Pages
|
||||
/Kids [4 0 R]
|
||||
/Count 1
|
||||
>>
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<<
|
||||
/Type /Page
|
||||
/Parent 3 0 R
|
||||
/MediaBox [0 0 612 792]
|
||||
/Contents 5 0 R
|
||||
/Resources <<
|
||||
/ProcSet [/PDF /Text]
|
||||
/Font << /F1 6 0 R >>
|
||||
>>
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<<
|
||||
/Length 5
|
||||
/Filter [/ASCIIHexDecode /RunLengthDecode /RunLengthDecode /RunLengthDecode /RunLengthDecode /RunLengthDecode /RunLengthDecode /RunLengthDecode /RunLengthDecode]
|
||||
>>
|
||||
stream
|
||||
8181>
|
||||
endstream
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<<
|
||||
/Type /Font
|
||||
/Subtype /Type1
|
||||
/Name /F1
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /MacRomanEncoding
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000079 00000 n
|
||||
0000000128 00000 n
|
||||
0000000189 00000 n
|
||||
0000000381 00000 n
|
||||
0000000600 00000 n
|
||||
trailer
|
||||
<<
|
||||
/Size 7
|
||||
/Root 1 0 R
|
||||
>>
|
||||
startxref
|
||||
714
|
||||
%%EOF
|
||||
@@ -59,10 +59,21 @@
|
||||
{
|
||||
var filters = filterProvider.GetFilters(stream.StreamDictionary);
|
||||
|
||||
double totalMaxEstSize = stream.Data.Length * 100;
|
||||
|
||||
var transform = stream.Data;
|
||||
for (var i = 0; i < filters.Count; i++)
|
||||
{
|
||||
transform = filters[i].Decode(transform, stream.StreamDictionary, filterProvider, i);
|
||||
var filter = filters[i];
|
||||
totalMaxEstSize *= GetEstimatedSizeMultiplier(filter);
|
||||
|
||||
transform = filter.Decode(transform, stream.StreamDictionary, filterProvider, i);
|
||||
|
||||
if (i < filters.Count - 1 && transform.Length > totalMaxEstSize)
|
||||
{
|
||||
// Try to prevent malicious decompression, leading to OOM issues
|
||||
throw new PdfDocumentFormatException($"Decoded stream size exceeds the estimated maximum size. Current decoded stream length: {transform.Length}, {i + 1} filters applied out of {filters.Count}.");
|
||||
}
|
||||
}
|
||||
|
||||
return transform;
|
||||
@@ -75,15 +86,38 @@
|
||||
{
|
||||
var filters = filterProvider.GetFilters(stream.StreamDictionary, scanner);
|
||||
|
||||
double totalMaxEstSize = stream.Data.Length * 100;
|
||||
|
||||
var transform = stream.Data;
|
||||
for (var i = 0; i < filters.Count; i++)
|
||||
{
|
||||
transform = filters[i].Decode(transform, stream.StreamDictionary, filterProvider, i);
|
||||
var filter = filters[i];
|
||||
totalMaxEstSize *= GetEstimatedSizeMultiplier(filter);
|
||||
|
||||
transform = filter.Decode(transform, stream.StreamDictionary, filterProvider, i);
|
||||
|
||||
if (i < filters.Count - 1 && transform.Length > totalMaxEstSize)
|
||||
{
|
||||
// Try to prevent malicious decompression, leading to OOM issues
|
||||
throw new PdfDocumentFormatException($"Decoded stream size exceeds the estimated maximum size. Current decoded stream length: {transform.Length}, {i + 1} filters applied out of {filters.Count}.");
|
||||
}
|
||||
}
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
private static double GetEstimatedSizeMultiplier(IFilter filter)
|
||||
{
|
||||
return filter switch
|
||||
{
|
||||
AsciiHexDecodeFilter => 0.5,
|
||||
Ascii85Filter => 0.8,
|
||||
FlateFilter or RunLengthFilter => 3,
|
||||
LzwFilter => 2,
|
||||
_ => 1000
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an equivalent token where any indirect references of child objects are
|
||||
/// recursively traversed and resolved.
|
||||
|
||||
Reference in New Issue
Block a user