Check for potential write error (or not buffer full consumed)

This commit is contained in:
Grégory Soutadé 2022-12-23 17:51:01 +01:00
parent c22babf3c4
commit 68371b9b17
3 changed files with 37 additions and 15 deletions

View File

@ -118,6 +118,7 @@ namespace uPDFParser
Name* parseName(std::string& token); Name* parseName(std::string& token);
void repairTrailer(); void repairTrailer();
void writeBuffer(int fd, const char* buffer, int size);
void writeUpdate(const std::string& filename); void writeUpdate(const std::string& filename);
int version_major, version_minor; int version_major, version_minor;

View File

@ -22,7 +22,8 @@ namespace uPDFParser
INVALID_OBJECT, INVALID_OBJECT,
INVALID_TRAILER, INVALID_TRAILER,
INVALID_HEXASTRING, INVALID_HEXASTRING,
NOT_IMPLEMENTED NOT_IMPLEMENTED,
IO_ERROR
}; };

View File

@ -619,7 +619,9 @@ namespace uPDFParser
for (;endOffset > startOffset; endOffset--) for (;endOffset > startOffset; endOffset--)
{ {
lseek(fd, -1, SEEK_CUR); lseek(fd, -1, SEEK_CUR);
read(fd, &c, 1); ret = read(fd, &c, 1);
if (ret <= 0)
break;
if (c != '\n' && c != '\r') if (c != '\n' && c != '\r')
break; break;
lseek(fd, -1, SEEK_CUR); lseek(fd, -1, SEEK_CUR);
@ -824,6 +826,24 @@ namespace uPDFParser
trailer.dictionary().addData(keys[i], (*xrefObject)[keys[i]]->clone()); trailer.dictionary().addData(keys[i], (*xrefObject)[keys[i]]->clone());
} }
} }
void Parser::writeBuffer(int fd, const char* buffer, int size)
{
int ret;
do {
ret = ::write(fd, buffer, size);
if (ret >= 0)
{
size -= ret;
buffer += ret;
}
else
{
EXCEPTION(IO_ERROR, "IO Error (write) %m");
}
} while (size);
}
void Parser::writeUpdate(const std::string& filename) void Parser::writeUpdate(const std::string& filename)
{ {
@ -848,11 +868,11 @@ namespace uPDFParser
ret = ::read(fd, buffer, sizeof(buffer)); ret = ::read(fd, buffer, sizeof(buffer));
if (ret <= 0) if (ret <= 0)
break; break;
::write(newFd, buffer, ret); writeBuffer(newFd, buffer, ret);
} }
} }
::write(newFd, "\r", 1); writeBuffer(newFd, "\r", 1);
int maxId = 0; int maxId = 0;
std::stringstream xref; std::stringstream xref;
@ -872,7 +892,7 @@ namespace uPDFParser
nbNewObjects ++; nbNewObjects ++;
std::string objStr = object->str(); std::string objStr = object->str();
curOffset = lseek(newFd, 0, SEEK_CUR); curOffset = lseek(newFd, 0, SEEK_CUR);
::write(newFd, objStr.c_str(), objStr.size()); writeBuffer(newFd, objStr.c_str(), objStr.size());
xref << std::setw(0) << object->objectId() << " 1\n"; xref << std::setw(0) << object->objectId() << " 1\n";
xref << std::setw(10) << curOffset << " " << std::setw(5) << object->generationNumber() << " n\r\n"; // Here \r seems important xref << std::setw(10) << curOffset << " " << std::setw(5) << object->generationNumber() << " n\r\n"; // Here \r seems important
} }
@ -886,7 +906,7 @@ namespace uPDFParser
off_t newXrefOffset = lseek(newFd, 0, SEEK_CUR); off_t newXrefOffset = lseek(newFd, 0, SEEK_CUR);
std::string xrefStr = xref.str(); std::string xrefStr = xref.str();
::write(newFd, xrefStr.c_str(), xrefStr.size()); writeBuffer(newFd, xrefStr.c_str(), xrefStr.size());
trailer.deleteKey("Prev"); trailer.deleteKey("Prev");
if (xrefOffset != (off_t)-1) if (xrefOffset != (off_t)-1)
@ -895,14 +915,14 @@ namespace uPDFParser
trailer.dictionary().addData("Size", new Integer(maxId+1)); trailer.dictionary().addData("Size", new Integer(maxId+1));
std::string trailerStr = trailer.dictionary().str(); std::string trailerStr = trailer.dictionary().str();
::write(newFd, "trailer\n", 8); writeBuffer(newFd, "trailer\n", 8);
::write(newFd, trailerStr.c_str(), trailerStr.size()); writeBuffer(newFd, trailerStr.c_str(), trailerStr.size());
std::stringstream startxref; std::stringstream startxref;
startxref << "startxref\n" << newXrefOffset << "\n%%EOF"; startxref << "startxref\n" << newXrefOffset << "\n%%EOF";
std::string startxrefStr = startxref.str(); std::string startxrefStr = startxref.str();
::write(newFd, startxrefStr.c_str(), startxrefStr.size()); writeBuffer(newFd, startxrefStr.c_str(), startxrefStr.size());
close(newFd); close(newFd);
} }
@ -922,7 +942,7 @@ namespace uPDFParser
version_major, version_minor, version_major, version_minor,
0xe2, 0xe3, 0xcf, 0xd3); 0xe2, 0xe3, 0xcf, 0xd3);
::write(newFd, header, ret); writeBuffer(newFd, header, ret);
int maxId = 0; int maxId = 0;
std::stringstream xref; std::stringstream xref;
@ -939,7 +959,7 @@ namespace uPDFParser
Object* object = *it; Object* object = *it;
std::string objStr = object->str(); std::string objStr = object->str();
curOffset = lseek(newFd, 0, SEEK_CUR); curOffset = lseek(newFd, 0, SEEK_CUR);
::write(newFd, objStr.c_str(), objStr.size()); writeBuffer(newFd, objStr.c_str(), objStr.size());
xref << std::setw(0) << object->objectId() << " 1\n"; xref << std::setw(0) << object->objectId() << " 1\n";
xref << std::setw(10) << curOffset << " " << std::setw(5) << object->generationNumber(); xref << std::setw(10) << curOffset << " " << std::setw(5) << object->generationNumber();
if (object->used()) if (object->used())
@ -966,7 +986,7 @@ namespace uPDFParser
off_t newXrefOffset = lseek(newFd, 0, SEEK_CUR); off_t newXrefOffset = lseek(newFd, 0, SEEK_CUR);
std::string xrefStr = xref.str(); std::string xrefStr = xref.str();
::write(newFd, xrefStr.c_str(), xrefStr.size()); writeBuffer(newFd, xrefStr.c_str(), xrefStr.size());
trailer.deleteKey("Prev"); trailer.deleteKey("Prev");
trailer.deleteKey("Size"); trailer.deleteKey("Size");
@ -977,14 +997,14 @@ namespace uPDFParser
trailer.dictionary().addData("XRefStm", new Integer(xrefStmOffset)); trailer.dictionary().addData("XRefStm", new Integer(xrefStmOffset));
std::string trailerStr = trailer.dictionary().str(); std::string trailerStr = trailer.dictionary().str();
::write(newFd, "trailer\n", 8); writeBuffer(newFd, "trailer\n", 8);
::write(newFd, trailerStr.c_str(), trailerStr.size()); writeBuffer(newFd, trailerStr.c_str(), trailerStr.size());
std::stringstream startxref; std::stringstream startxref;
startxref << "startxref\n" << newXrefOffset << "\n%%EOF"; startxref << "startxref\n" << newXrefOffset << "\n%%EOF";
std::string startxrefStr = startxref.str(); std::string startxrefStr = startxref.str();
::write(newFd, startxrefStr.c_str(), startxrefStr.size()); writeBuffer(newFd, startxrefStr.c_str(), startxrefStr.size());
close(newFd); close(newFd);
} }