diff --git a/fofi/FoFiBase.cc b/fofi/FoFiBase.cc index ef8992a..52ed27d 100644 --- a/fofi/FoFiBase.cc +++ b/fofi/FoFiBase.cc @@ -14,6 +14,7 @@ #include #include "goo/gmem.h" +#include "Error.h" #include "FoFiBase.h" //------------------------------------------------------------------------ @@ -38,11 +39,18 @@ char *FoFiBase::readFile(char *fileName, int *fileLen) { int n; if (!(f = fopen(fileName, "rb"))) { + error(-1, "Cannot open '%s'", fileName); + return NULL; + } + if (fseek(f, 0, SEEK_END) != 0) { + error(-1, "Cannot seek to end of file"); return NULL; } - fseek(f, 0, SEEK_END); n = (int)ftell(f); - fseek(f, 0, SEEK_SET); + if (fseek(f, 0, SEEK_SET) != 0) { + error(-1, "Cannot seek to start of file"); + return NULL; + } buf = (char *)gmalloc(n); if ((int)fread(buf, 1, n, f) != n) { gfree(buf); diff --git a/poppler/GfxFont.cc b/poppler/GfxFont.cc index 655e259..eeff005 100644 --- a/poppler/GfxFont.cc +++ b/poppler/GfxFont.cc @@ -408,9 +408,15 @@ char *GfxFont::readExtFontFile(int *len) { error(-1, "External font file '%s' vanished", extFontFile->getCString()); return NULL; } - fseek(f, 0, SEEK_END); + if (fseek(f, 0, SEEK_END) != 0) { + error(-1, "Cannot seek to end of file"); + return NULL; + } *len = (int)ftell(f); - fseek(f, 0, SEEK_SET); + if (fseek(f, 0, SEEK_SET) != 0) { + error(-1, "Cannot seek to start of file"); + return NULL; + } buf = (char *)gmalloc(*len); if ((int)fread(buf, 1, *len, f) != *len) { error(-1, "Error reading external font file '%s'", diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc index c0c8f58..00ba925 100644 --- a/poppler/PDFDoc.cc +++ b/poppler/PDFDoc.cc @@ -181,6 +181,7 @@ PDFDoc::PDFDoc(BaseStream *strA, GooString *ownerPassword, } GBool PDFDoc::setup(GooString *ownerPassword, GooString *userPassword) { + if (!str->checkIO()) return false; str->reset(); // check footer @@ -447,6 +448,7 @@ GBool PDFDoc::saveAs(GooString *name, PDFWriteMode mode) { return gFalse; } outStr = new FileOutStream(f,0); + if (!outStr->checkIO()) return false; res = saveAs(outStr, mode); delete outStr; fclose(f); @@ -489,6 +491,7 @@ GBool PDFDoc::saveWithoutChangesAs(GooString *name) { } outStr = new FileOutStream(f,0); + if (!outStr->checkIO()) return false; res = saveWithoutChangesAs(outStr); delete outStr; diff --git a/poppler/Stream.cc b/poppler/Stream.cc index 3ef7146..a8f7480 100644 --- a/poppler/Stream.cc +++ b/poppler/Stream.cc @@ -308,9 +308,16 @@ FileOutStream::~FileOutStream () close (); } +bool FileOutStream::checkIO () +{ + if (fseek(f, 1, SEEK_SET) == 0 && fseek(f, 0, SEEK_SET) == 0) return true; + error(-1, "Output file not seekable"); + return false; +} + void FileOutStream::reset () { - fseek(f, start, SEEK_SET); + fseek(f, start, SEEK_SET); // ignore failure } void FileOutStream::close () @@ -652,12 +659,19 @@ FileStream::~FileStream() { close(); } +bool FileStream::checkIO() { + if (fseek(f, 1, SEEK_SET) == 0 && fseek(f, 0, SEEK_SET) == 0) return true; + error(-1, "File empty or not seekable"); + return false; +} + Stream *FileStream::makeSubStream(Guint startA, GBool limitedA, Guint lengthA, Object *dictA) { return new FileStream(f, startA, limitedA, lengthA, dictA); } void FileStream::reset() { + // Ignore failure of any seek functions. #if HAVE_FSEEKO savePos = (Guint)ftello(f); fseeko(f, start, SEEK_SET); @@ -674,6 +688,7 @@ void FileStream::reset() { } void FileStream::close() { + // Ignore failure of any seek functions. if (saved) { #if HAVE_FSEEKO fseeko(f, savePos, SEEK_SET); @@ -710,6 +725,7 @@ GBool FileStream::fillBuf() { void FileStream::setPos(Guint pos, int dir) { Guint size; + // Ignore failure of any seek functions. if (dir >= 0) { #if HAVE_FSEEKO fseeko(f, pos, SEEK_SET); diff --git a/poppler/Stream.h b/poppler/Stream.h index 74152fc..3a99fa8 100644 --- a/poppler/Stream.h +++ b/poppler/Stream.h @@ -177,6 +177,9 @@ public: // Printf-like function 2,3 because the first arg is class instance ? virtual void printf (const char *format, ...) = 0 ; //__attribute__((format(printf, 2,3))) = 0; + // Similar to Stream::checkIO(), this makes sure fseek() etc. will work. + virtual bool checkIO() = 0; + private: int ref; // reference count @@ -191,6 +194,8 @@ public: virtual ~FileOutStream (); + virtual bool checkIO(); + virtual void reset(); virtual void close(); @@ -231,6 +236,16 @@ public: virtual Guint getStart() = 0; virtual void moveStart(int delta) = 0; + // Check that any necessary I/O for this stream is working. + // In particular, for file streams this happens to check + // that fseek() works. Call this after constructing the + // stream. + // + // If something is wrong so the stream is unlikely to work, + // this function logs a message and returns false. + // + virtual bool checkIO() = 0; + private: Object dict; @@ -350,6 +365,7 @@ public: FileStream(FILE *fA, Guint startA, GBool limitedA, Guint lengthA, Object *dictA); virtual ~FileStream(); + virtual bool checkIO(); virtual Stream *makeSubStream(Guint startA, GBool limitedA, Guint lengthA, Object *dictA); virtual StreamKind getKind() { return strFile; } @@ -392,6 +408,7 @@ public: MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); virtual ~MemStream(); + virtual bool checkIO() { return true; } virtual Stream *makeSubStream(Guint start, GBool limited, Guint lengthA, Object *dictA); virtual StreamKind getKind() { return strWeird; } @@ -438,6 +455,7 @@ public: EmbedStream(Stream *strA, Object *dictA, GBool limitedA, Guint lengthA); virtual ~EmbedStream(); + virtual bool checkIO() { return true; } virtual Stream *makeSubStream(Guint start, GBool limitedA, Guint lengthA, Object *dictA); virtual StreamKind getKind() { return str->getKind(); } diff --git a/utils/pdfinfo.cc b/utils/pdfinfo.cc index 5dbd724..ab9a6f0 100644 --- a/utils/pdfinfo.cc +++ b/utils/pdfinfo.cc @@ -135,7 +135,10 @@ int main(int argc, char *argv[]) { Object obj; obj.initNull(); - doc = new PDFDoc(new FileStream(stdin, 0, gFalse, 0, &obj), ownerPW, userPW); + + FileStream *stream = new FileStream(stdin, 0, gFalse, 0, &obj); + if (!stream->checkIO()) exit(1); + doc = new PDFDoc(stream, ownerPW, userPW); } if (userPW) { @@ -258,14 +261,14 @@ int main(int argc, char *argv[]) { #endif if (f) { #if HAVE_FSEEKO - fseeko(f, 0, SEEK_END); - printf("File size: %u bytes\n", (Guint)ftello(f)); + if (fseeko(f, 0, SEEK_END) == 0) + printf("File size: %u bytes\n", (Guint)ftello(f)); #elif HAVE_FSEEK64 - fseek64(f, 0, SEEK_END); - printf("File size: %u bytes\n", (Guint)ftell64(f)); + if (fseek64(f, 0, SEEK_END) == 0) + printf("File size: %u bytes\n", (Guint)ftell64(f)); #else - fseek(f, 0, SEEK_END); - printf("File size: %d bytes\n", (int)ftell(f)); + if (fseek(f, 0, SEEK_END) == 0) + printf("File size: %d bytes\n", (int)ftell(f)); #endif fclose(f); } diff --git a/utils/pdftoppm.cc b/utils/pdftoppm.cc index 164679d..f61502f 100644 --- a/utils/pdftoppm.cc +++ b/utils/pdftoppm.cc @@ -190,7 +190,10 @@ int main(int argc, char *argv[]) { Object obj; obj.initNull(); - doc = new PDFDoc(new FileStream(stdin, 0, gFalse, 0, &obj), ownerPW, userPW); + + FileStream *stream = new FileStream(stdin, 0, gFalse, 0, &obj); + if (!stream->checkIO()) exit(1); + doc = new PDFDoc(stream, ownerPW, userPW); } if (userPW) { delete userPW; diff --git a/utils/pdftotext.cc b/utils/pdftotext.cc index a0caed8..c7b0a14 100644 --- a/utils/pdftotext.cc +++ b/utils/pdftotext.cc @@ -154,7 +154,10 @@ int main(int argc, char *argv[]) { Object obj; obj.initNull(); - doc = new PDFDoc(new FileStream(stdin, 0, gFalse, 0, &obj), ownerPW, userPW); + + FileStream *stream = new FileStream(stdin, 0, gFalse, 0, &obj); + if (!stream->checkIO()) exit(1); + doc = new PDFDoc(stream, ownerPW, userPW); } if (userPW) {