1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-03-05 15:05:48 +02:00

Align checksum page error list in manifest file packs.

This was left unaligned on purpose to save space but the sanitizer did not like it. Since this field is seldom used go ahead and align it to make the sanitizer happy.

Also add some macros to make working with alignment easier.

Found with -fsanitize=undefined.
This commit is contained in:
David Steele 2022-03-24 17:55:38 -06:00
parent 3dd7960451
commit 50ee4b19fe
2 changed files with 22 additions and 6 deletions

View File

@ -85,4 +85,18 @@ Adapted from PostgreSQL src/include/c.h.
((type)(expression))
#endif
/***********************************************************************************************************************************
Determine the alignment of a data type
This macro reduces to a constant so it is safe to use anywhere a constant is allowed, e.g. a switch statement case.
***********************************************************************************************************************************/
#define ALIGN_OF(type) ((size_t)&((struct {char c; type t;} *)0)->t)
/***********************************************************************************************************************************
Determine the byte offset required to align a type after an arbitrary number of bytes
This is useful for determining how to correctly align a type in a buffer that is being dynamically built up like a struct.
***********************************************************************************************************************************/
#define ALIGN_OFFSET(type, bytes) (ALIGN_OF(type) - ((bytes) % ALIGN_OF(type)))
#endif

View File

@ -315,16 +315,18 @@ manifestFilePack(const Manifest *const manifest, const ManifestFile *const file)
}
// Allocate memory for the file pack
const size_t nameSize = strSize(file->name) + 1;
uint8_t *const result = memNew(
sizeof(StringPub) + strSize(file->name) + 1 + bufferPos + (file->checksumPageErrorList != NULL ?
sizeof(StringPub) + strSize(file->checksumPageErrorList) + 1 : 0));
sizeof(StringPub) + nameSize + bufferPos + (file->checksumPageErrorList != NULL ?
ALIGN_OFFSET(StringPub, nameSize + bufferPos) + sizeof(StringPub) + strSize(file->checksumPageErrorList) + 1 : 0));
// Create string object for the file name
*(StringPub *)result = (StringPub){.size = (unsigned int)strSize(file->name), .buffer = (char *)result + sizeof(StringPub)};
size_t resultPos = sizeof(StringPub);
memcpy(result + resultPos, (uint8_t *)strZ(file->name), strSize(file->name) + 1);
resultPos += strSize(file->name) + 1;
memcpy(result + resultPos, (uint8_t *)strZ(file->name), nameSize);
resultPos += nameSize;
// Copy pack data
memcpy(result + resultPos, buffer, bufferPos);
@ -332,7 +334,7 @@ manifestFilePack(const Manifest *const manifest, const ManifestFile *const file)
// Create string object for the checksum error list
if (file->checksumPageErrorList != NULL)
{
resultPos += bufferPos;
resultPos += bufferPos + ALIGN_OFFSET(StringPub, nameSize + bufferPos);
*(StringPub *)(result + resultPos) = (StringPub)
{.size = (unsigned int)strSize(file->checksumPageErrorList), .buffer = (char *)result + resultPos + sizeof(StringPub)};
@ -414,7 +416,7 @@ manifestFileUnpack(const Manifest *const manifest, const ManifestFilePack *const
result.checksumPageError = flag & (1 << manifestFilePackFlagChecksumPageError) ? true : false;
if (flag & (1 << manifestFilePackFlagChecksumPageErrorList))
result.checksumPageErrorList = (const String *)((const uint8_t *)filePack + bufferPos);
result.checksumPageErrorList = (const String *)((const uint8_t *)filePack + bufferPos + ALIGN_OFFSET(StringPub, bufferPos));
FUNCTION_TEST_RETURN(result);
}