Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crash / stack overflow with malformed input pdf #51

Closed
hannob opened this issue Sep 2, 2015 · 8 comments
Closed

crash / stack overflow with malformed input pdf #51

hannob opened this issue Sep 2, 2015 · 8 comments

Comments

@hannob
Copy link

hannob commented Sep 2, 2015

Passing this pdf to qpdf will cause a crash:
https://crashes.fuzzing-project.org/qpdf-crash.pdf

Looking at the stack trace this seems to be an endless recursion causing a stack overflow.

Here's (part of) the stack trace when compiling qpdf with address sanitizer (latest git code):

==10615==ERROR: AddressSanitizer: stack-overflow on address 0x7ffdede32820 (pc 0x7f5ddac0dce7 bp 0x7ffdede33e50 sp 0x7ffdede32810 T0)
    #0 0x7f5ddac0dce6 in pcre_compile2 (/lib64/libpcre.so.1+0xace6)
    #1 0x78342b in PCRE::PCRE(char const*, int) /mnt/ram/qpdf/libqpdf/PCRE.cc:144:18
    #2 0x5ece64 in QPDFTokenizer::resolveLiteral() /mnt/ram/qpdf/libqpdf/QPDFTokenizer.cc:62:10
    #3 0x5f19be in QPDFTokenizer::presentCharacter(char) /mnt/ram/qpdf/libqpdf/QPDFTokenizer.cc:432:9
    #4 0x5f5091 in QPDFTokenizer::readToken(PointerHolder<InputSource>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /mnt/ram/qpdf/libqpdf/QPDFTokenizer.cc:519:6
    #5 0x5c461b in QPDFObjectHandle::parseInternal(PointerHolder<InputSource>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, QPDFTokenizer&, bool&, QPDFObjectHandle::StringDecrypter*, QPDF*, bool, bool, bool) /mnt/ram/qpdf/libqpdf/QPDFObjectHandle.cc:873:13
    #6 0x5c4c07 in QPDFObjectHandle::parseInternal(PointerHolder<InputSource>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, QPDFTokenizer&, bool&, QPDFObjectHandle::StringDecrypter*, QPDF*, bool, bool, bool) /mnt/ram/qpdf/libqpdf/QPDFObjectHandle.cc:939:15
    #7 0x5bcf0c in QPDFObjectHandle::parse(PointerHolder<InputSource>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, QPDFTokenizer&, bool&, QPDFObjectHandle::StringDecrypter*, QPDF*) /mnt/ram/qpdf/libqpdf/QPDFObjectHandle.cc:841:12
    #8 0x53b4d0 in QPDF::readObject(PointerHolder<InputSource>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, bool) /mnt/ram/qpdf/libqpdf/QPDF.cc:1020:31
    #9 0x550b21 in QPDF::readObjectAtOffset(bool, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, int&, int&) /mnt/ram/qpdf/libqpdf/QPDF.cc:1396:27
    #10 0x565da2 in QPDF::resolve(int, int) /mnt/ram/qpdf/libqpdf/QPDF.cc:1477:7
    #11 0x5a71e7 in QPDF::Resolver::resolve(QPDF*, int, int) /mnt/ram/qpdf/include/qpdf/QPDF.hh:520:13
    #12 0x5a71e7 in QPDFObjectHandle::dereference() /mnt/ram/qpdf/libqpdf/QPDFObjectHandle.cc:1520
    #13 0x5a88ca in QPDFObjectHandle::isInteger() /mnt/ram/qpdf/libqpdf/QPDFObjectHandle.cc:145:5
    #14 0x53d465 in QPDF::readObject(PointerHolder<InputSource>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, bool) /mnt/ram/qpdf/libqpdf/QPDF.cc:1121:23
    #15 0x550b21 in QPDF::readObjectAtOffset(bool, long long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, int&, int&) /mnt/ram/qpdf/libqpdf/QPDF.cc:1396:27
    #16 0x565da2 in QPDF::resolve(int, int) /mnt/ram/qpdf/libqpdf/QPDF.cc:1477:7
    #17 0x5a71e7 in QPDF::Resolver::resolve(QPDF*, int, int) /mnt/ram/qpdf/include/qpdf/QPDF.hh:520:13
    #18 0x5a71e7 in QPDFObjectHandle::dereference() /mnt/ram/qpdf/libqpdf/QPDFObjectHandle.cc:1520
    #19 0x5a88ca in QPDFObjectHandle::isInteger() /mnt/ram/qpdf/libqpdf/QPDFObjectHandle.cc:145:5
    #20 0x53d465 in QPDF::readObject(PointerHolder<InputSource>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, bool) /mnt/ram/qpdf/libqpdf/QPDF.cc:1121:23
@jberkenbilt
Copy link
Contributor

Note to self: saved as qpdf/misc/bugs/51.pdf

I don't see a crash, but this looks like it may be addressed by the fixes to several other issues involving handling malformed dictionaries. See #36, #45, #64.

@hannob
Copy link
Author

hannob commented Sep 11, 2016

Hmm, surprised you don't see the crash. Still crashes for me with the latest git code.
As the crash actually happens in libpcre it may be a bug in there...

@jberkenbilt
Copy link
Contributor

One of the things I hope to do in the next update is to use from c++11 if building with a c++11 compiler and using pcre as a fallback if not available. What version of pcre are you using?

@hannob
Copy link
Author

hannob commented Sep 13, 2016

8.39, latest upstream version.

@asarubbo
Copy link

I can reproduce this issue.

This was referenced Feb 13, 2017
@jberkenbilt
Copy link
Contributor

I am able to reproduce the issue. I am hoping to get to it imminently. I have found fixes for #100 and #101. Next I am going to investigate this and #99.

jberkenbilt added a commit to jberkenbilt/qpdf that referenced this issue Jul 26, 2017
During parsing of an object, sometimes parts of the object have to be
resolved. An example is stream lengths. If such an object directly or
indirectly points to the object being parsed, it can cause an infinite
loop. Guard against all cases of re-entrant resolution of objects.
@jberkenbilt
Copy link
Contributor

This one also has an easy fix.

jberkenbilt added a commit to jberkenbilt/qpdf that referenced this issue Jul 26, 2017
During parsing of an object, sometimes parts of the object have to be
resolved. An example is stream lengths. If such an object directly or
indirectly points to the object being parsed, it can cause an infinite
loop. Guard against all cases of re-entrant resolution of objects.
jberkenbilt added a commit to jberkenbilt/qpdf that referenced this issue Jul 26, 2017
During parsing of an object, sometimes parts of the object have to be
resolved. An example is stream lengths. If such an object directly or
indirectly points to the object being parsed, it can cause an infinite
loop. Guard against all cases of re-entrant resolution of objects.
jberkenbilt added a commit to jberkenbilt/qpdf that referenced this issue Jul 26, 2017
During parsing of an object, sometimes parts of the object have to be
resolved. An example is stream lengths. If such an object directly or
indirectly points to the object being parsed, it can cause an infinite
loop. Guard against all cases of re-entrant resolution of objects.
jberkenbilt added a commit to jberkenbilt/qpdf that referenced this issue Jul 26, 2017
During parsing of an object, sometimes parts of the object have to be
resolved. An example is stream lengths. If such an object directly or
indirectly points to the object being parsed, it can cause an infinite
loop. Guard against all cases of re-entrant resolution of objects.
@ghost
Copy link

ghost commented Feb 14, 2018

This has been assigned CVE-2015-9252

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants