From 315092dd98d5230ef0efa18b294d464d0e9f79d0 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Tue, 25 Jul 2017 10:21:27 -0400 Subject: [PATCH] Avoid xref reconstruction infinite loop (fixes #100) This is CVE-2017-9209. --- ChangeLog | 4 ++++ include/qpdf/QPDF.hh | 1 + libqpdf/QPDF.cc | 10 ++++++++++ qpdf/qtest/qpdf.test | 3 ++- qpdf/qtest/qpdf/issue-100.out | 5 +++++ qpdf/qtest/qpdf/issue-100.pdf | Bin 0 -> 1145 bytes 6 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 qpdf/qtest/qpdf/issue-100.out create mode 100644 qpdf/qtest/qpdf/issue-100.pdf diff --git a/ChangeLog b/ChangeLog index 32bafad6..ce0ce1e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2017-07-26 Jay Berkenbilt + * CVE-2017-9209: Fix infinite loop caused by attempting to + reconstruct the xref table while already in the process of + reconstructing the xref table. + * CVE-2017-9210: Fix infinite loop caused by attempting to unparse an object for inclusion in the text of an exception. diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index 88acf6c5..f7a31edf 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -1075,6 +1075,7 @@ class QPDF // copied_stream_data_provider is owned by copied_streams CopiedStreamDataProvider* copied_stream_data_provider; std::set attachment_streams; + bool reconstructed_xref; // Linearization data qpdf_offset_t first_xref_item_offset; // actual value from file diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index b8a1601c..a50c87ad 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -93,6 +93,7 @@ QPDF::QPDF() : cached_key_generation(0), pushed_inherited_attributes_to_pages(false), copied_stream_data_provider(0), + reconstructed_xref(false), first_xref_item_offset(0), uncompressed_after_compressed(false) { @@ -331,6 +332,15 @@ QPDF::setTrailer(QPDFObjectHandle obj) void QPDF::reconstruct_xref(QPDFExc& e) { + if (this->reconstructed_xref) + { + // Avoid xref reconstruction infinite loops + QTC::TC("qpdf", "QPDF caught recursive xref reconstruction"); + throw e; + } + + this->reconstructed_xref = true; + PCRE obj_re("^\\s*(\\d+)\\s+(\\d+)\\s+obj\\b"); PCRE endobj_re("^\\s*endobj\\b"); PCRE trailer_re("^\\s*trailer\\b"); diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index e0b2609a..dd8dad30 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -206,7 +206,7 @@ $td->runtest("remove page we don't have", show_ntests(); # ---------- $td->notify("--- Miscellaneous Tests ---"); -$n_tests += 78; +$n_tests += 79; $td->runtest("qpdf version", {$td->COMMAND => "qpdf --version"}, @@ -220,6 +220,7 @@ $td->runtest("C API: qpdf version", # Files to reproduce various bugs foreach my $d ( + ["100","xref reconstruction loop"], ["101", "resolve for exception text"], ) { diff --git a/qpdf/qtest/qpdf/issue-100.out b/qpdf/qtest/qpdf/issue-100.out new file mode 100644 index 00000000..37bd3207 --- /dev/null +++ b/qpdf/qtest/qpdf/issue-100.out @@ -0,0 +1,5 @@ +WARNING: issue-100.pdf: file is damaged +WARNING: issue-100.pdf (file position 736): xref not found +WARNING: issue-100.pdf: Attempting to reconstruct cross-reference table +WARNING: issue-100.pdf (object 5 0, file position 489): attempting to recover stream length +issue-100.pdf (object 6 0, file position 59): expected n n obj diff --git a/qpdf/qtest/qpdf/issue-100.pdf b/qpdf/qtest/qpdf/issue-100.pdf new file mode 100644 index 0000000000000000000000000000000000000000..fc418b3bd376effc7d680086e734fc5545176e0d GIT binary patch literal 1145 zcmah|&ubGw6wXa}7`%AwVJ@L9Md!!P&hAQxbbmph)tU-|r9w<6ZQ5j4Hd`p(?L`FX zP4M7F@Z?P|Ue!Oue?bq5miT6O)5f&m!0wy<_M12Fee=!r#zq+5;5TKhR)cY#>Fx-w zWS~JOJNqDoi2ycXBz?RO%_g*31~MO@N_27t@De}@(Dwc1f{Q$Nx_WtL@lmGxz=#Ko zF`Jla(lGOcm?;4aEW-^+2WZD+s)`$4{q+o9kk{YpKTkg$*O!U{t!fA576lj8o!3m) zbh4Z85mRr6#)Dz5Ga3)Oxej$N-O<&5PF$(nm5(3p3>R1L{rLQ~y|8t1yMFTh?Hl;= zvVMH+&!gW2)_U*i%P0)l2D)8!xX|qG0%eGtcU|grdU0GX!c>6s<_Y9kcQDjO1iCqx zO!D!D&VqFGBu#XZ6L;E{X%s~|>x*u#cgF{1w==>W)tcgKq&OGLzZRaqlF79iq znLYmT#8XW?+DX%#IHd>LNk1j#y5R}5L$XDhj%&Li^L!auB9bAG{74Ev@Py>Ti2}a` z|ECzMhiNa^)4hZ7;fT;U41~&hdR$$pb>_#uBjUhvlr6m2T~#s+rLXK&RXVVn<;8_} LECr25bT@{-DoQST literal 0 HcmV?d00001