From 1082e1671afd8ab91583dabc876304008acb021c Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 16 Oct 2009 23:17:22 +0200 Subject: Some "security" fixes based on newly released Xpdf 3.02pl4 --- poppler/Stream.cc | 4 ++++ poppler/XRef.cc | 19 +++++++++++++++---- splash/Splash.cc | 7 +++++++ splash/SplashBitmap.cc | 37 ++++++++++++++++++++++++++++++------- splash/SplashErrorCodes.h | 4 +++- 5 files changed, 59 insertions(+), 12 deletions(-) diff --git a/poppler/Stream.cc b/poppler/Stream.cc index 7137c5ea..6634317a 100644 --- a/poppler/Stream.cc +++ b/poppler/Stream.cc @@ -405,6 +405,10 @@ ImageStream::ImageStream(Stream *strA, int widthA, int nCompsA, int nBitsA) { } else { imgLineSize = nVals; } + if (width > INT_MAX / nComps) { + // force a call to gmallocn(-1,...), which will throw an exception + imgLineSize = -1; + } imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar)); imgIdx = nVals; } diff --git a/poppler/XRef.cc b/poppler/XRef.cc index 832a0384..e5fd92a7 100644 --- a/poppler/XRef.cc +++ b/poppler/XRef.cc @@ -76,6 +76,8 @@ public: // generation 0. ObjectStream(XRef *xref, int objStrNumA); + GBool isOk() { return ok; } + ~ObjectStream(); // Return the object number of this object stream. @@ -91,6 +93,7 @@ private: int nObjects; // number of objects in the stream Object *objs; // the objects (length = nObjects) int *objNums; // the object numbers (length = nObjects) + GBool ok; }; ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { @@ -104,6 +107,7 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { nObjects = 0; objs = NULL; objNums = NULL; + ok = gFalse; if (!xref->fetch(objStrNum, 0, &objStr)->isStream()) { goto err1; @@ -129,11 +133,13 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { goto err1; } - if (nObjects >= INT_MAX / (int)sizeof(int)) { - error(-1, "Invalid 'nObjects'"); + // this is an arbitrary limit to avoid integer overflow problems + // in the 'new Object[nObjects]' call (Acrobat apparently limits + // object streams to 100-200 objects) + if (nObjects > 1000000) { + error(-1, "Too many objects in an object stream"); goto err1; } - objs = new Object[nObjects]; objNums = (int *)gmallocn(nObjects, sizeof(int)); offsets = (int *)gmallocn(nObjects, sizeof(int)); @@ -190,10 +196,10 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { } gfree(offsets); + ok = gTrue; err1: objStr.free(); - return; } ObjectStream::~ObjectStream() { @@ -970,6 +976,11 @@ Object *XRef::fetch(int num, int gen, Object *obj) { delete objStr; } objStr = new ObjectStream(this, e->offset); + if (!objStr->isOk()) { + delete objStr; + objStr = NULL; + goto err; + } } objStr->getObject(e->gen, num, obj); break; diff --git a/splash/Splash.cc b/splash/Splash.cc index a1deb854..834cb109 100644 --- a/splash/Splash.cc +++ b/splash/Splash.cc @@ -27,6 +27,7 @@ #include #include +#include #include "goo/gmem.h" #include "SplashErrorCodes.h" #include "SplashMath.h" @@ -2001,6 +2002,9 @@ SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData, xq = w % scaledWidth; // allocate pixel buffer + if (yp < 0 || yp > INT_MAX - 1) { + return splashErrBadArg; + } pixBuf = (SplashColorPtr)gmallocn((yp + 1), w); // initialize the pixel pipe @@ -2301,6 +2305,9 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData, xq = w % scaledWidth; // allocate pixel buffers + if (yp < 0 || yp > INT_MAX - 1) { + return splashErrBadArg; + } colorBuf = (SplashColorPtr)gmallocn3((yp + 1), w, nComps); if (srcAlpha) { alphaBuf = (Guchar *)gmallocn((yp + 1), w); diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc index 2337a62c..999efd1a 100644 --- a/splash/SplashBitmap.cc +++ b/splash/SplashBitmap.cc @@ -29,6 +29,7 @@ #include #include +#include #include "goo/gmem.h" #include "SplashErrorCodes.h" #include "SplashBitmap.h" @@ -48,26 +49,48 @@ SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPad, mode = modeA; switch (mode) { case splashModeMono1: - rowSize = (width + 7) >> 3; + if (width > 0) { + rowSize = (width + 7) >> 3; + } else { + rowSize = -1; + } break; case splashModeMono8: - rowSize = width; + if (width > 0) { + rowSize = width; + } else { + rowSize = -1; + } break; case splashModeRGB8: case splashModeBGR8: - rowSize = width * 3; + if (width > 0 && width <= INT_MAX / 3) { + rowSize = width * 3; + } else { + rowSize = -1; + } break; case splashModeXBGR8: - rowSize = width * 4; + if (width > 0 && width <= INT_MAX / 4) { + rowSize = width * 4; + } else { + rowSize = -1; + } break; #if SPLASH_CMYK case splashModeCMYK8: - rowSize = width * 4; + if (width > 0 && width <= INT_MAX / 4) { + rowSize = width * 4; + } else { + rowSize = -1; + } break; #endif } - rowSize += rowPad - 1; - rowSize -= rowSize % rowPad; + if (rowSize > 0) { + rowSize += rowPad - 1; + rowSize -= rowSize % rowPad; + } data = (SplashColorPtr)gmallocn(rowSize, height); if (!topDown) { data += (height - 1) * rowSize; diff --git a/splash/SplashErrorCodes.h b/splash/SplashErrorCodes.h index 9c309826..d1f81f85 100644 --- a/splash/SplashErrorCodes.h +++ b/splash/SplashErrorCodes.h @@ -41,7 +41,9 @@ #define splashErrSingularMatrix 8 // matrix is singular -#define splashErrZeroImage 9 // image of 0x0 +#define splashErrBadArg 9 // bad argument + +#define splashErrZeroImage 254 // image of 0x0 #define splashErrGeneric 255 -- cgit v1.2.3