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);
void repairTrailer();
void writeBuffer(int fd, const char* buffer, int size);
void writeUpdate(const std::string& filename);
int version_major, version_minor;

View File

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

View File

@ -619,7 +619,9 @@ namespace uPDFParser
for (;endOffset > startOffset; endOffset--)
{
lseek(fd, -1, SEEK_CUR);
read(fd, &c, 1);
ret = read(fd, &c, 1);
if (ret <= 0)
break;
if (c != '\n' && c != '\r')
break;
lseek(fd, -1, SEEK_CUR);
@ -824,6 +826,24 @@ namespace uPDFParser
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)
{
@ -848,11 +868,11 @@ namespace uPDFParser
ret = ::read(fd, buffer, sizeof(buffer));
if (ret <= 0)
break;
::write(newFd, buffer, ret);
writeBuffer(newFd, buffer, ret);
}
}
::write(newFd, "\r", 1);
writeBuffer(newFd, "\r", 1);
int maxId = 0;
std::stringstream xref;
@ -872,7 +892,7 @@ namespace uPDFParser
nbNewObjects ++;
std::string objStr = object->str();
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(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);
std::string xrefStr = xref.str();
::write(newFd, xrefStr.c_str(), xrefStr.size());
writeBuffer(newFd, xrefStr.c_str(), xrefStr.size());
trailer.deleteKey("Prev");
if (xrefOffset != (off_t)-1)
@ -895,14 +915,14 @@ namespace uPDFParser
trailer.dictionary().addData("Size", new Integer(maxId+1));
std::string trailerStr = trailer.dictionary().str();
::write(newFd, "trailer\n", 8);
::write(newFd, trailerStr.c_str(), trailerStr.size());
writeBuffer(newFd, "trailer\n", 8);
writeBuffer(newFd, trailerStr.c_str(), trailerStr.size());
std::stringstream startxref;
startxref << "startxref\n" << newXrefOffset << "\n%%EOF";
std::string startxrefStr = startxref.str();
::write(newFd, startxrefStr.c_str(), startxrefStr.size());
writeBuffer(newFd, startxrefStr.c_str(), startxrefStr.size());
close(newFd);
}
@ -922,7 +942,7 @@ namespace uPDFParser
version_major, version_minor,
0xe2, 0xe3, 0xcf, 0xd3);
::write(newFd, header, ret);
writeBuffer(newFd, header, ret);
int maxId = 0;
std::stringstream xref;
@ -939,7 +959,7 @@ namespace uPDFParser
Object* object = *it;
std::string objStr = object->str();
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(10) << curOffset << " " << std::setw(5) << object->generationNumber();
if (object->used())
@ -966,7 +986,7 @@ namespace uPDFParser
off_t newXrefOffset = lseek(newFd, 0, SEEK_CUR);
std::string xrefStr = xref.str();
::write(newFd, xrefStr.c_str(), xrefStr.size());
writeBuffer(newFd, xrefStr.c_str(), xrefStr.size());
trailer.deleteKey("Prev");
trailer.deleteKey("Size");
@ -977,14 +997,14 @@ namespace uPDFParser
trailer.dictionary().addData("XRefStm", new Integer(xrefStmOffset));
std::string trailerStr = trailer.dictionary().str();
::write(newFd, "trailer\n", 8);
::write(newFd, trailerStr.c_str(), trailerStr.size());
writeBuffer(newFd, "trailer\n", 8);
writeBuffer(newFd, trailerStr.c_str(), trailerStr.size());
std::stringstream startxref;
startxref << "startxref\n" << newXrefOffset << "\n%%EOF";
std::string startxrefStr = startxref.str();
::write(newFd, startxrefStr.c_str(), startxrefStr.size());
writeBuffer(newFd, startxrefStr.c_str(), startxrefStr.size());
close(newFd);
}