From e79bce2f493d13133cb8dda658e4a378db6172df Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sat, 15 Dec 2012 22:49:57 +1030 Subject: [PATCH 2/5] Add Int64 object type --- poppler/Lexer.cc | 46 +++++++++++++++++++------------------------- poppler/Object.cc | 6 +++--- poppler/Object.h | 23 +++++++++++----------- poppler/PDFDoc.cc | 4 ++-- poppler/SecurityHandler.cc | 4 ++-- qt4/tests/check_lexer.cpp | 24 ++++++++++++++++------- test/pdf-fullrewrite.cc | 9 +-------- 7 files changed, 57 insertions(+), 59 deletions(-) diff --git a/poppler/Lexer.cc b/poppler/Lexer.cc index 01b730b..948b5a8 100644 --- a/poppler/Lexer.cc +++ b/poppler/Lexer.cc @@ -62,6 +62,7 @@ static const char specialChars[256] = { }; static const int IntegerSafeLimit = (INT_MAX - 9) / 10; +static const long long LongLongSafeLimit = (LLONG_MAX - 9) / 10; //------------------------------------------------------------------------ // Lexer @@ -155,10 +156,10 @@ int Lexer::lookChar() { Object *Lexer::getObj(Object *obj, int objNum) { char *p; int c, c2; - GBool comment, neg, done, overflownInteger, overflownUnsignedInteger; + GBool comment, neg, done, overflownInteger, overflownLongLong; int numParen; int xi; - unsigned int xui = 0; + long long xll = 0; double xf = 0, scale; GooString *s; int n, m; @@ -187,7 +188,7 @@ Object *Lexer::getObj(Object *obj, int objNum) { case '5': case '6': case '7': case '8': case '9': case '+': case '-': case '.': overflownInteger = gFalse; - overflownUnsignedInteger = gFalse; + overflownLongLong = gFalse; neg = gFalse; xi = 0; if (c == '-') { @@ -201,23 +202,21 @@ Object *Lexer::getObj(Object *obj, int objNum) { c = lookChar(); if (isdigit(c)) { getChar(); - if (unlikely(overflownInteger)) { - if (overflownUnsignedInteger) { - xf = xf * 10.0 + (c - '0'); + if (unlikely(overflownLongLong)) { + xf = xf * 10.0 + (c - '0'); + } else if (unlikely (overflownInteger)) { + if (unlikely(xll > LongLongSafeLimit) && + (xll > (LLONG_MAX - (c - '0')) / 10.0)) { + overflownLongLong = gTrue; + xf = xll * 10.0 + (c - '0'); } else { - overflownUnsignedInteger = gTrue; - xf = xui * 10.0 + (c - '0'); + xll = xll * 10 + (c - '0'); } } else { if (unlikely(xi > IntegerSafeLimit) && (xi > (INT_MAX - (c - '0')) / 10.0)) { overflownInteger = gTrue; - if (xi > (UINT_MAX - (c - '0')) / 10.0) { - overflownUnsignedInteger = gTrue; - xf = xi * 10.0 + (c - '0'); - } else { - xui = xi * 10.0 + (c - '0'); - } + xll = xi * 10LL + (c - '0'); } else { xi = xi * 10 + (c - '0'); } @@ -231,22 +230,17 @@ Object *Lexer::getObj(Object *obj, int objNum) { } if (neg) { xi = -xi; + xll = -xll; xf = -xf; } if (unlikely(overflownInteger)) { - if (overflownUnsignedInteger) { + if (overflownLongLong) { obj->initReal(xf); } else { - if (neg) { - if (xui-1 == INT_MAX) { - obj->initInt(INT_MIN); - } else { - xf = xui; - xf = -xf; - obj->initReal(xf); - } + if (unlikely(xll == INT_MIN)) { + obj->initInt(INT_MIN); } else { - obj->initUint(xui); + obj->initInt64(xll); } } } else { @@ -256,8 +250,8 @@ Object *Lexer::getObj(Object *obj, int objNum) { doReal: if (likely(!overflownInteger)) { xf = xi; - } else if (!overflownUnsignedInteger) { - xf = xui; + } else if (!overflownLongLong) { + xf = xll; } scale = 0.1; while (1) { diff --git a/poppler/Object.cc b/poppler/Object.cc index 1963b7f..8999a0e 100644 --- a/poppler/Object.cc +++ b/poppler/Object.cc @@ -53,7 +53,7 @@ static const char *objTypeNames[numObjTypes] = { "error", "eof", "none", - "unsigned integer" + "integer64" }; #ifdef DEBUG_MEM @@ -224,8 +224,8 @@ void Object::print(FILE *f) { case objNone: fprintf(f, ""); break; - case objUint: - fprintf(f, "%u", uintg); + case objInt64: + fprintf(f, "%lld", int64g); break; } } diff --git a/poppler/Object.h b/poppler/Object.h index 09ac5dd..86da9b0 100644 --- a/poppler/Object.h +++ b/poppler/Object.h @@ -48,10 +48,10 @@ abort(); \ } -#define OBJECT_2TYPES_CHECK(wanted_type1, wanted_type2) \ - if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2)) { \ +#define OBJECT_3TYPES_CHECK(wanted_type1, wanted_type2, wanted_type3) \ + if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2) && unlikely(type != wanted_type3)) { \ error(errInternal, 0, (char *) "Call to Object where the object was type {0:d}, " \ - "not the expected type {1:d} or {2:d}", type, wanted_type1, wanted_type2); \ + "not the expected type {1:d}, {2:d} or {3:d}", type, wanted_type1, wanted_type2, wanted_type3); \ abort(); \ } @@ -95,7 +95,7 @@ enum ObjType { objNone, // uninitialized object // poppler-only objects - objUint // overflown integer that still fits in a unsigned integer + objInt64 // integer with at least 64-bits }; #define numObjTypes 15 // total number of object types @@ -144,8 +144,8 @@ public: { initObj(objError); return this; } Object *initEOF() { initObj(objEOF); return this; } - Object *initUint(unsigned int uintgA) - { initObj(objUint); uintg = uintgA; return this; } + Object *initInt64(long long int64gA) + { initObj(objInt64); int64g = int64gA; return this; } // Copy an object. Object *copy(Object *obj); @@ -166,7 +166,7 @@ public: GBool isBool() { return type == objBool; } GBool isInt() { return type == objInt; } GBool isReal() { return type == objReal; } - GBool isNum() { return type == objInt || type == objReal; } + GBool isNum() { return type == objInt || type == objReal || type == objInt64; } GBool isString() { return type == objString; } GBool isName() { return type == objName; } GBool isNull() { return type == objNull; } @@ -178,7 +178,7 @@ public: GBool isError() { return type == objError; } GBool isEOF() { return type == objEOF; } GBool isNone() { return type == objNone; } - GBool isUint() { return type == objUint; } + GBool isInt64() { return type == objInt64; } // Special type checking. GBool isName(const char *nameA) @@ -192,7 +192,8 @@ public: GBool getBool() { OBJECT_TYPE_CHECK(objBool); return booln; } int getInt() { OBJECT_TYPE_CHECK(objInt); return intg; } double getReal() { OBJECT_TYPE_CHECK(objReal); return real; } - double getNum() { OBJECT_2TYPES_CHECK(objInt, objReal); return type == objInt ? (double)intg : real; } + double getNum() { OBJECT_3TYPES_CHECK(objInt, objInt64, objReal); + return type == objInt ? (double)intg : type == objInt64 ? (double)int64g : real; } GooString *getString() { OBJECT_TYPE_CHECK(objString); return string; } char *getName() { OBJECT_TYPE_CHECK(objName); return name; } Array *getArray() { OBJECT_TYPE_CHECK(objArray); return array; } @@ -202,7 +203,7 @@ public: int getRefNum() { OBJECT_TYPE_CHECK(objRef); return ref.num; } int getRefGen() { OBJECT_TYPE_CHECK(objRef); return ref.gen; } char *getCmd() { OBJECT_TYPE_CHECK(objCmd); return cmd; } - unsigned int getUint() { OBJECT_TYPE_CHECK(objUint); return uintg; } + long long getInt64() { OBJECT_TYPE_CHECK(objInt64); return int64g; } // Array accessors. int arrayGetLength(); @@ -247,7 +248,7 @@ private: union { // value for each type: GBool booln; // boolean int intg; // integer - unsigned int uintg; // unsigned integer + long long int64g; // 64-bit integer double real; // real GooString *string; // string char *name; // name diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc index 7a3dc39..df11a16 100644 --- a/poppler/PDFDoc.cc +++ b/poppler/PDFDoc.cc @@ -1122,8 +1122,8 @@ void PDFDoc::writeObject (Object* obj, OutStream* outStr, XRef *xRef, Guint numO case objInt: outStr->printf("%i ", obj->getInt()); break; - case objUint: - outStr->printf("%u ", obj->getUint()); + case objInt64: + outStr->printf("%lli ", obj->getInt64()); break; case objReal: { diff --git a/poppler/SecurityHandler.cc b/poppler/SecurityHandler.cc index a48449a..fad0863 100644 --- a/poppler/SecurityHandler.cc +++ b/poppler/SecurityHandler.cc @@ -167,8 +167,8 @@ StandardSecurityHandler::StandardSecurityHandler(PDFDoc *docA, encryptDictA->dictLookup("OE", &ownerEncObj); encryptDictA->dictLookup("UE", &userEncObj); encryptDictA->dictLookup("P", &permObj); - if (permObj.isUint()) { - unsigned int permUint = permObj.getUint(); + if (permObj.isInt64()) { + unsigned int permUint = permObj.getInt64(); int perms = permUint - UINT_MAX - 1; permObj.free(); permObj.initInt(perms); diff --git a/qt4/tests/check_lexer.cpp b/qt4/tests/check_lexer.cpp index 1ae849f..ea834c8 100644 --- a/qt4/tests/check_lexer.cpp +++ b/qt4/tests/check_lexer.cpp @@ -12,7 +12,7 @@ private slots: void TestLexer::testNumbers() { - char *data = "0 1 -1 2147483647 -2147483647 2147483648 -2147483648 4294967297 -2147483649 0.1 1.1 -1.1 2147483647.1 -2147483647.1 2147483648.1 -2147483648.1 4294967297.1 -2147483649.1"; + char *data = "0 1 -1 2147483647 -2147483647 2147483648 -2147483648 4294967297 -2147483649 0.1 1.1 -1.1 2147483647.1 -2147483647.1 2147483648.1 -2147483648.1 4294967297.1 -2147483649.1 9223372036854775807 18446744073709551615"; Object dummy; MemStream *stream = new MemStream(data, 0, strlen(data), &dummy); Lexer *lexer = new Lexer(NULL, stream); @@ -46,8 +46,8 @@ void TestLexer::testNumbers() obj.free(); lexer->getObj(&obj); - QCOMPARE(obj.getType(), objUint); - QCOMPARE(obj.getUint(), 2147483648u); + QCOMPARE(obj.getType(), objInt64); + QCOMPARE(obj.getInt64(), 2147483648ll); obj.free(); lexer->getObj(&obj); @@ -56,13 +56,13 @@ void TestLexer::testNumbers() obj.free(); lexer->getObj(&obj); - QCOMPARE(obj.getType(), objReal); - QCOMPARE(obj.getReal(), 4294967297.); + QCOMPARE(obj.getType(), objInt64); + QCOMPARE(obj.getInt64(), 4294967297ll); obj.free(); lexer->getObj(&obj); - QCOMPARE(obj.getType(), objReal); - QCOMPARE(obj.getReal(), -2147483649.); + QCOMPARE(obj.getType(), objInt64); + QCOMPARE(obj.getInt64(), -2147483649ll); obj.free(); lexer->getObj(&obj); @@ -110,6 +110,16 @@ void TestLexer::testNumbers() QCOMPARE(obj.getReal(), -2147483649.1); obj.free(); + lexer->getObj(&obj); + QCOMPARE(obj.getType(), objInt64); + QCOMPARE(obj.getInt64(), 9223372036854775807ll); + obj.free(); + + lexer->getObj(&obj); + QCOMPARE(obj.getType(), objReal); + QCOMPARE(obj.getReal(), 18446744073709551616.); + obj.free(); + delete lexer; } diff --git a/test/pdf-fullrewrite.cc b/test/pdf-fullrewrite.cc index 2b912f7..8108372 100644 --- a/test/pdf-fullrewrite.cc +++ b/test/pdf-fullrewrite.cc @@ -149,6 +149,7 @@ static GBool compareObjects(Object *objA, Object *objB) } } case objInt: + case objInt64: case objReal: { if (!objB->isNum()) { @@ -159,14 +160,6 @@ static GBool compareObjects(Object *objA, Object *objB) return (-0.01 < diff) && (diff < 0.01); } } - case objUint: - { - if (objB->getType() != objUint) { - return gFalse; - } else { - return (objA->getUint() == objB->getUint()); - } - } case objString: { if (objB->getType() != objString) { -- 1.7.10.4