CESA-2004-007 - rev 1
xpdf-2.03 example integer overflow and integer arithmetic flaws
===============================================================
Programs affected: xpdf, gpdf and kpdf.
Severity: Unassessed.
This advisory lists code flaws discovered by inspection of the xpdf-2.03
code. Note that the GNOME and KDE PDF browsers seem to be based on xpdf.
This advisory follows on from CESA-2004-002, which looked at xpdf-3.0. In
response to feedback, xpdf-2.03 was briefly examined. The reason for this is
that xpdf-2.03 and derivatives are currently very common. For example, kpdf
in all released versions is based on xpdf-2 (this may change with KDE 3.3.1).
Flaw 1. Multiple integer overflows possible when allocating memory.
For example, XRef.cc: 79
entries = (XRefEntry *)gmalloc(size * sizeof(XRefEntry));
"size" is an arbitrary signed int and comes from the PDF.
XRef.cc: 286
if (first + n > size) {
newSize = first + n;
entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
"first" and "n" are arbitrary signed ints and come from the PDF. Not only
might the addition overflow, but also games can be played by makking one or
both negative. After the addition, the multiplication for thr grealloc() might
overflow.
Catalog.cc:68
pages = (Page **)gmalloc(pagesSize * sizeof(Page *));
pageRefs = (Ref *)gmalloc(pagesSize * sizeof(Ref));
"pageSize" is an arbitrary signed int from the PDF.
Demo PDF: http://scary.beasts.org/misc/bad5.pdf
Flaw 2. Integer overflows leading to out of bounds write.
XRef.cc:436
if (num >= size) {
newSize = (num + 1 + 255) & ~255;
entries = (XRefEntry *)
grealloc(entries, newSize * sizeof(XRefEntry));
for (i = size; i < newSize; ++i) {
entries[i].offset = 0xffffffff;
entries[i].used = gFalse;
}
size = newSize;
}
if (!entries[num].used || gen >= entries[num].gen) {
entries[num].offset = pos - start;
entries[num].gen = gen;
entries[num].used = gTrue;
}
"num" and "gen" are arbitrary signed ints from the PDF file. This causes a
problem with integer overflow on the memory allocation. But more seriously,
a negative value of "num" leads (with minor restrictions) to an out of bounds
write to the heap[*]. One of the values written is "gen" - an arbitrary int
from the PDF file.
[*] - with a sufficiently negative value of "num", I don't see why the write
access couldn't be so out of bounds that it in fact writes into the stack.
Demo PDF: http://scary.beasts.org/misc/bad4.pdf
CESA-2004-007 - rev 1
Chris Evans
chris@scary.beasts.org
[Advertisement: I am interested in moving into a security related field
full-time. E-mail me to discuss.]