mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +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);
|
||||
uint16_t offset = patch.offset + section.offset;
|
||||
|
||||
// `jr` is quite unlike the others...
|
||||
if (patch.type == PATCHTYPE_JR) {
|
||||
struct {
|
||||
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
|
||||
// PC as operand to `jr` is lower than reference PC by 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;
|
||||
} else {
|
||||
// Patch a certain number of bytes
|
||||
struct {
|
||||
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))
|
||||
if (!isError && (value < type.min || value > type.max))
|
||||
error(
|
||||
patch.src,
|
||||
patch.lineNo,
|
||||
"Value %" PRId32 "%s is not %u-bit",
|
||||
value,
|
||||
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;
|
||||
value >>= 8;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user