1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2026-10-23 21:28:56 +03:00

Check pack field sizes against the bytes remaining in a buffer.

pckReadBin() and pckReadPack() allocate a buffer of the size stored for a field before reading the field. A pack read from a buffer with a corrupt size could allocate far more memory than the pack holds before failing with unexpected EOF.

Error when the size of a field is larger than the bytes remaining in the buffer. A pack read through an IoRead still allocates the size stored for the field because the total size is not known.
This commit is contained in:
David Steele
2026-10-12 11:16:00 +02:00
parent 6963016c77
commit 0966ebbb3e
2 changed files with 13 additions and 0 deletions

View File

@@ -600,6 +600,9 @@ pckReadTagNext(PackRead *const this)
(this->tagNextValue > 0 || !packTypeMapData[this->tagNextTypeMap].valueSingleBit))
{
this->tagNextSize = (size_t)pckReadU64Internal(this);
// A pack read from a buffer cannot have a field larger than the bytes remaining
CHECK(FormatError, this->read != NULL || this->tagNextSize <= this->bufferUsed - this->bufferPos, "unexpected EOF");
}
else
this->tagNextSize = 0;

View File

@@ -334,6 +334,16 @@ testRun(void)
TEST_ASSIGN(packRead, pckReadNew(pckFromBuf(BUFSTRDEF(""))), "new read");
TEST_ERROR(pckReadBuffer(packRead, 2), FormatError, "unexpected EOF");
TEST_ASSIGN(packWrite, pckWriteNewP(), "new write");
TEST_RESULT_VOID(pckWriteStrP(packWrite, STRDEF("abc")), "write string");
TEST_RESULT_VOID(pckWriteEndP(packWrite), "write end");
const Buffer *const packStr = pckToBuf(pckWriteResult(packWrite));
TEST_ASSIGN(
packRead, pckReadNewC(bufPtrConst(packStr), bufUsed(packStr) - 2), "new read without the last string byte and end");
TEST_ERROR(pckReadStrP(packRead), FormatError, "unexpected EOF");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("error on invalid uint64");