![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /usr/share/emscripten/tests/poppler/poppler/ |
Upload File : |
//======================================================================== // // Hints.cc // // This file is licensed under the GPLv2 or later // // Copyright 2010 Hib Eris <hib@hiberis.nl> // Copyright 2010 Albert Astals Cid <aacid@kde.org> // Copyright 2010 Pino Toscano <pino@kde.org> // //======================================================================== #include <config.h> #include "Hints.h" #include "Linearization.h" #include "Object.h" #include "Stream.h" #include "XRef.h" #include "Parser.h" #include "Lexer.h" #include "SecurityHandler.h" #include <limits.h> //------------------------------------------------------------------------ // Hints //------------------------------------------------------------------------ Hints::Hints(BaseStream *str, Linearization *linearization, XRef *xref, SecurityHandler *secHdlr) { mainXRefEntriesOffset = linearization->getMainXRefEntriesOffset(); nPages = linearization->getNumPages(); pageFirst = linearization->getPageFirst(); pageEndFirst = linearization->getEndFirst(); pageObjectFirst = linearization->getObjectNumberFirst(); if (pageObjectFirst < 0 || pageObjectFirst >= xref->getNumObjects()) { error(-1, "Invalid reference for first page object (%d) in linearization table ", pageObjectFirst); pageObjectFirst = 0; } pageOffsetFirst = xref->getEntry(pageObjectFirst)->offset; if (nPages >= INT_MAX / (int)sizeof(Guint)) { error(-1, "Invalid number of pages (%d) for hints table", nPages); nPages = 0; } nObjects = (Guint *) gmallocn_checkoverflow(nPages, sizeof(Guint)); pageObjectNum = (int *) gmallocn_checkoverflow(nPages, sizeof(int)); xRefOffset = (Guint *) gmallocn_checkoverflow(nPages, sizeof(Guint)); pageLength = (Guint *) gmallocn_checkoverflow(nPages, sizeof(Guint)); pageOffset = (Guint *) gmallocn_checkoverflow(nPages, sizeof(Guint)); numSharedObject = (Guint *) gmallocn_checkoverflow(nPages, sizeof(Guint)); sharedObjectId = (Guint **) gmallocn_checkoverflow(nPages, sizeof(Guint*)); if (!nObjects || !pageObjectNum || !xRefOffset || !pageLength || !pageOffset || !numSharedObject || !sharedObjectId) { error(-1, "Failed to allocate memory for hints tabel"); nPages = 0; } memset(numSharedObject, 0, nPages * sizeof(Guint)); nSharedGroups = 0; groupLength = NULL; groupOffset = NULL; groupHasSignature = NULL; groupNumObjects = NULL; groupXRefOffset = NULL; readTables(str, linearization, xref, secHdlr); } Hints::~Hints() { gfree(nObjects); gfree(pageObjectNum); gfree(xRefOffset); gfree(pageLength); gfree(pageOffset); for (int i=0; i< nPages; i++) { if (numSharedObject[i]) { gfree(sharedObjectId[i]); } } gfree(sharedObjectId); gfree(numSharedObject); gfree(groupLength); gfree(groupOffset); gfree(groupHasSignature); gfree(groupNumObjects); gfree(groupXRefOffset); } void Hints::readTables(BaseStream *str, Linearization *linearization, XRef *xref, SecurityHandler *secHdlr) { hintsOffset = linearization->getHintsOffset(); hintsLength = linearization->getHintsLength(); hintsOffset2 = linearization->getHintsOffset2(); hintsLength2 = linearization->getHintsLength2(); Parser *parser; Object obj; int bufLength = hintsLength + hintsLength2; std::vector<char> buf(bufLength); char *p = &buf[0]; obj.initNull(); Stream *s = str->makeSubStream(hintsOffset, gFalse, hintsLength, &obj); s->reset(); for (Guint i=0; i < hintsLength; i++) { *p++ = s->getChar(); } delete s; if (hintsOffset2 && hintsLength2) { obj.initNull(); s = str->makeSubStream(hintsOffset2, gFalse, hintsLength2, &obj); s->reset(); for (Guint i=0; i < hintsLength2; i++) { *p++ = s->getChar(); } delete s; } obj.initNull(); MemStream *memStream = new MemStream (&buf[0], 0, bufLength, &obj); obj.initNull(); parser = new Parser(xref, new Lexer(xref, memStream), gTrue); int num, gen; if (parser->getObj(&obj)->isInt() && (num = obj.getInt(), obj.free(), parser->getObj(&obj)->isInt()) && (gen = obj.getInt(), obj.free(), parser->getObj(&obj)->isCmd("obj")) && (obj.free(), parser->getObj(&obj, secHdlr ? secHdlr->getFileKey() : (Guchar *)NULL, secHdlr ? secHdlr->getEncAlgorithm() : cryptRC4, secHdlr ? secHdlr->getFileKeyLength() : 0, num, gen)->isStream())) { Stream *hintsStream = obj.getStream(); Dict *hintsDict = obj.streamGetDict(); int sharedStreamOffset = 0; if (hintsDict->lookupInt("S", NULL, &sharedStreamOffset) && sharedStreamOffset > 0) { hintsStream->reset(); readPageOffsetTable(hintsStream); hintsStream->reset(); for (int i=0; i<sharedStreamOffset; i++) hintsStream->getChar(); readSharedObjectsTable(hintsStream); } else { error(-1, "Invalid shared object hint table offset"); } } else { error(-1, "Failed parsing hints table object"); } obj.free(); delete parser; } void Hints::readPageOffsetTable(Stream *str) { if (nPages < 1) { error(-1, "Invalid number of pages reading page offset hints table"); return; } inputBits = 0; // reset on byte boundary. nObjectLeast = readBits(32, str); objectOffsetFirst = readBits(32, str); if (objectOffsetFirst >= hintsOffset) objectOffsetFirst += hintsLength; nBitsDiffObjects = readBits(16, str); pageLengthLeast = readBits(32, str); nBitsDiffPageLength = readBits(16, str); OffsetStreamLeast = readBits(32, str); nBitsOffsetStream = readBits(16, str); lengthStreamLeast = readBits(32, str); nBitsLengthStream = readBits(16, str); nBitsNumShared = readBits(16, str); nBitsShared = readBits(16, str); nBitsNumerator = readBits(16, str); denominator = readBits(16, str); for (int i=0; i<nPages; i++) { nObjects[i] = nObjectLeast + readBits(nBitsDiffObjects, str); } nObjects[0] = 0; xRefOffset[0] = mainXRefEntriesOffset + 20; for (int i=1; i<nPages; i++) { xRefOffset[i] = xRefOffset[i-1] + 20*nObjects[i-1]; } pageObjectNum[0] = 1; for (int i=1; i<nPages; i++) { pageObjectNum[i] = pageObjectNum[i-1] + nObjects[i-1]; } pageObjectNum[0] = pageObjectFirst; inputBits = 0; // reset on byte boundary. Not in specs! for (int i=0; i<nPages; i++) { pageLength[i] = pageLengthLeast + readBits(nBitsDiffPageLength, str); } inputBits = 0; // reset on byte boundary. Not in specs! numSharedObject[0] = readBits(nBitsNumShared, str); numSharedObject[0] = 0; // Do not trust the read value to be 0. sharedObjectId[0] = NULL; for (int i=1; i<nPages; i++) { numSharedObject[i] = readBits(nBitsNumShared, str); if (numSharedObject[i] >= INT_MAX / (int)sizeof(Guint)) { error(-1, "Invalid number of shared objects"); numSharedObject[i] = 0; return; } sharedObjectId[i] = (Guint *) gmallocn_checkoverflow(numSharedObject[i], sizeof(Guint)); if (numSharedObject[i] && !sharedObjectId[i]) { error(-1, "Failed to allocate memory for shared object IDs"); numSharedObject[i] = 0; return; } } inputBits = 0; // reset on byte boundary. Not in specs! for (int i=1; i<nPages; i++) { for (Guint j=0; j < numSharedObject[i]; j++) { sharedObjectId[i][j] = readBits(nBitsShared, str); } } pageOffset[0] = pageOffsetFirst; // find pageOffsets. for (int i=1; i<nPages; i++) { pageOffset[i] = pageOffset[i-1] + pageLength[i-1]; } } void Hints::readSharedObjectsTable(Stream *str) { inputBits = 0; // reset on byte boundary. Guint firstSharedObjectNumber = readBits(32, str); Guint firstSharedObjectOffset = readBits(32, str); firstSharedObjectOffset += hintsLength; Guint nSharedGroupsFirst = readBits(32, str); Guint nSharedGroups = readBits(32, str); Guint nBitsNumObjects = readBits(16, str); Guint groupLengthLeast = readBits(32, str); Guint nBitsDiffGroupLength = readBits(16, str); if ((!nSharedGroups) || (nSharedGroups >= INT_MAX / (int)sizeof(Guint))) { error(-1, "Invalid number of shared object groups"); nSharedGroups = 0; return; } if ((!nSharedGroupsFirst) || (nSharedGroupsFirst > nSharedGroups)) { error(-1, "Invalid number of first page shared object groups"); nSharedGroupsFirst = nSharedGroups; } groupLength = (Guint *) gmallocn_checkoverflow(nSharedGroups, sizeof(Guint)); groupOffset = (Guint *) gmallocn_checkoverflow(nSharedGroups, sizeof(Guint)); groupHasSignature = (Guint *) gmallocn_checkoverflow(nSharedGroups, sizeof(Guint)); groupNumObjects = (Guint *) gmallocn_checkoverflow(nSharedGroups, sizeof(Guint)); groupXRefOffset = (Guint *) gmallocn_checkoverflow(nSharedGroups, sizeof(Guint)); if (!groupLength || !groupOffset || !groupHasSignature || !groupNumObjects || !groupXRefOffset) { error(-1, "Failed to allocate memory for shared object groups"); nSharedGroups = 0; return; } inputBits = 0; // reset on byte boundary. Not in specs! for (Guint i=0; i<nSharedGroups; i++) { groupLength[i] = groupLengthLeast + readBits(nBitsDiffGroupLength, str); } groupOffset[0] = objectOffsetFirst; for (Guint i=1; i<nSharedGroupsFirst; i++) { groupOffset[i] = groupOffset[i-1] + groupLength[i-1]; } if (nSharedGroups > nSharedGroupsFirst ) { groupOffset[nSharedGroupsFirst] = firstSharedObjectOffset; for (Guint i=nSharedGroupsFirst+1; i<nSharedGroups; i++) { groupOffset[i] = groupOffset[i-1] + groupLength[i-1]; } } inputBits = 0; // reset on byte boundary. Not in specs! for (Guint i=0; i<nSharedGroups; i++) { groupHasSignature[i] = readBits(1, str); } inputBits = 0; // reset on byte boundary. Not in specs! for (Guint i=0; i<nSharedGroups; i++) { if (groupHasSignature[i]) { readBits(128, str); } } inputBits = 0; // reset on byte boundary. Not in specs! for (Guint i=0; i<nSharedGroups; i++) { groupNumObjects[i] = nBitsNumObjects ? 1 + readBits(nBitsNumObjects, str) : 1; } for (Guint i=0; i<nSharedGroupsFirst; i++) { groupNumObjects[i] = 0; groupXRefOffset[i] = 0; } if (nSharedGroups > nSharedGroupsFirst ) { groupXRefOffset[nSharedGroupsFirst] = mainXRefEntriesOffset + 20*firstSharedObjectNumber; for (Guint i=nSharedGroupsFirst+1; i<nSharedGroups; i++) { groupXRefOffset[i] = groupXRefOffset[i-1] + 20*groupNumObjects[i-1]; } } } Guint Hints::getPageOffset(int page) { if ((page < 1) || (page > nPages)) return 0; if (page-1 > pageFirst) return pageOffset[page-1]; else if (page-1 < pageFirst) return pageOffset[page]; else return pageOffset[0]; } std::vector<ByteRange>* Hints::getPageRanges(int page) { if ((page < 1) || (page > nPages)) return NULL; int idx; if (page-1 > pageFirst) idx = page-1; else if (page-1 < pageFirst) idx = page; else idx = 0; ByteRange pageRange; std::vector<ByteRange> *v = new std::vector<ByteRange>; pageRange.offset = pageOffset[idx]; pageRange.length = pageLength[idx]; v->push_back(pageRange); pageRange.offset = xRefOffset[idx]; pageRange.length = 20*nObjects[idx]; v->push_back(pageRange); for (Guint j=0; j<numSharedObject[idx]; j++) { Guint k = sharedObjectId[idx][j]; pageRange.offset = groupOffset[k]; pageRange.length = groupLength[k]; v->push_back(pageRange); pageRange.offset = groupXRefOffset[k]; pageRange.length = 20*groupNumObjects[k]; v->push_back(pageRange); } return v; } Guint Hints::readBit(Stream *str) { Guint bit; int c; if (inputBits == 0) { if ((c = str->getChar()) == EOF) { return (Guint) -1; } bitsBuffer = c; inputBits = 8; } bit = (bitsBuffer >> (inputBits - 1)) & 1; --inputBits; return bit; } Guint Hints::readBits(int n, Stream *str) { Guint bit, bits; if (n < 0) return -1; if (n == 0) return 0; if (n == 1) return readBit(str); bit = (readBit(str) << (n-1)); if (bit == (Guint) -1) return -1; bits = readBits(n-1, str); if (bits == (Guint) -1) return -1; return bit | bits; } int Hints::getPageObjectNum(int page) { if ((page < 1) || (page > nPages)) return 0; if (page-1 > pageFirst) return pageObjectNum[page-1]; else if (page-1 < pageFirst) return pageObjectNum[page]; else return pageObjectNum[0]; }