mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Check that there is enough room to write a patch when linking
Prevents segfaulting if a patch's offset is too large
This commit is contained in:
@@ -465,8 +465,28 @@ static void applyFilePatches(Section §ion, Section &dataSection) {
|
|||||||
int32_t value = computeRPNExpr(patch, *section.fileSymbols);
|
int32_t value = computeRPNExpr(patch, *section.fileSymbols);
|
||||||
uint16_t offset = patch.offset + section.offset;
|
uint16_t offset = patch.offset + section.offset;
|
||||||
|
|
||||||
// `jr` is quite unlike the others...
|
struct {
|
||||||
if (patch.type == PATCHTYPE_JR) {
|
uint8_t size;
|
||||||
|
int32_t min;
|
||||||
|
int32_t max;
|
||||||
|
} const types[PATCHTYPE_INVALID] = {
|
||||||
|
{1, -128, 255 }, // PATCHTYPE_BYTE
|
||||||
|
{2, -32768, 65536 }, // PATCHTYPE_WORD
|
||||||
|
{4, INT32_MIN, INT32_MAX}, // PATCHTYPE_LONG
|
||||||
|
{1, 0, 0 }, // PATCHTYPE_JR
|
||||||
|
};
|
||||||
|
auto const &type = types[patch.type];
|
||||||
|
|
||||||
|
if (dataSection.data.size() < offset + type.size) {
|
||||||
|
error(
|
||||||
|
patch.src,
|
||||||
|
patch.lineNo,
|
||||||
|
"Patch would write %zu bytes past the end of section \"%s\" (%zu bytes long)",
|
||||||
|
offset + type.size - dataSection.data.size(),
|
||||||
|
dataSection.name.c_str(),
|
||||||
|
dataSection.data.size()
|
||||||
|
);
|
||||||
|
} else if (patch.type == PATCHTYPE_JR) { // `jr` is quite unlike the others...
|
||||||
// Offset is relative to the byte *after* the operand
|
// Offset is relative to the byte *after* the operand
|
||||||
// PC as operand to `jr` is lower than reference PC by 2
|
// PC as operand to `jr` is lower than reference PC by 2
|
||||||
uint16_t address = patch.pcSection->org + patch.pcOffset + 2;
|
uint16_t address = patch.pcSection->org + patch.pcOffset + 2;
|
||||||
@@ -483,26 +503,16 @@ static void applyFilePatches(Section §ion, Section &dataSection) {
|
|||||||
dataSection.data[offset] = jumpOffset & 0xFF;
|
dataSection.data[offset] = jumpOffset & 0xFF;
|
||||||
} else {
|
} else {
|
||||||
// Patch a certain number of bytes
|
// Patch a certain number of bytes
|
||||||
struct {
|
if (!isError && (value < type.min || value > type.max))
|
||||||
uint8_t size;
|
|
||||||
int32_t min;
|
|
||||||
int32_t max;
|
|
||||||
} const types[PATCHTYPE_INVALID] = {
|
|
||||||
{1, -128, 255 }, // PATCHTYPE_BYTE
|
|
||||||
{2, -32768, 65536 }, // PATCHTYPE_WORD
|
|
||||||
{4, INT32_MIN, INT32_MAX}, // PATCHTYPE_LONG
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!isError && (value < types[patch.type].min || value > types[patch.type].max))
|
|
||||||
error(
|
error(
|
||||||
patch.src,
|
patch.src,
|
||||||
patch.lineNo,
|
patch.lineNo,
|
||||||
"Value %" PRId32 "%s is not %u-bit",
|
"Value %" PRId32 "%s is not %u-bit",
|
||||||
value,
|
value,
|
||||||
value < 0 ? " (maybe negative?)" : "",
|
value < 0 ? " (maybe negative?)" : "",
|
||||||
types[patch.type].size * 8U
|
type.size * 8U
|
||||||
);
|
);
|
||||||
for (uint8_t i = 0; i < types[patch.type].size; i++) {
|
for (uint8_t i = 0; i < type.size; i++) {
|
||||||
dataSection.data[offset + i] = value & 0xFF;
|
dataSection.data[offset + i] = value & 0xFF;
|
||||||
value >>= 8;
|
value >>= 8;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user