mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Prevent assertions outside sections from crashing
This commit is contained in:
@@ -22,6 +22,11 @@ struct Assertion {
|
|||||||
// enum AssertionType type; The `patch`'s field is instead re-used
|
// enum AssertionType type; The `patch`'s field is instead re-used
|
||||||
struct Section *section;
|
struct Section *section;
|
||||||
char *message;
|
char *message;
|
||||||
|
/*
|
||||||
|
* This would be redundant with `.section->fileSymbols`... but
|
||||||
|
* `section` is sometimes NULL!
|
||||||
|
*/
|
||||||
|
struct Symbol ** fileSymbols;
|
||||||
|
|
||||||
struct Assertion *next;
|
struct Assertion *next;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ bool out_CreateAssert(enum AssertionType type, struct Expression const *expr,
|
|||||||
static void writeassert(struct Assertion *assert, FILE *f)
|
static void writeassert(struct Assertion *assert, FILE *f)
|
||||||
{
|
{
|
||||||
writepatch(assert->patch, f);
|
writepatch(assert->patch, f);
|
||||||
fputlong(getsectid(assert->section), f);
|
fputlong(assert->section ? getsectid(assert->section) : -1, f);
|
||||||
fputstring(assert->message, f);
|
fputstring(assert->message, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ static void readAssertion(FILE *file, struct Assertion *assert,
|
|||||||
readPatch(file, &assert->patch, fileName, assertName, 0);
|
readPatch(file, &assert->patch, fileName, assertName, 0);
|
||||||
tryReadlong(sectionID, file, "%s: Cannot read assertion's section ID: %s",
|
tryReadlong(sectionID, file, "%s: Cannot read assertion's section ID: %s",
|
||||||
fileName);
|
fileName);
|
||||||
assert->section = fileSections[sectionID];
|
assert->section = sectionID == -1 ? NULL : fileSections[sectionID];
|
||||||
tryReadstr(assert->message, file, "%s: Cannot read assertion's message: %s",
|
tryReadstr(assert->message, file, "%s: Cannot read assertion's message: %s",
|
||||||
fileName);
|
fileName);
|
||||||
}
|
}
|
||||||
@@ -502,6 +502,7 @@ void obj_ReadFile(char const *fileName)
|
|||||||
if (!assertion)
|
if (!assertion)
|
||||||
err(1, "%s: Couldn't create new assertion", fileName);
|
err(1, "%s: Couldn't create new assertion", fileName);
|
||||||
readAssertion(file, assertion, fileName, fileSections, i);
|
readAssertion(file, assertion, fileName, fileSections, i);
|
||||||
|
assertion->fileSymbols = fileSymbols;
|
||||||
assertion->next = assertions;
|
assertion->next = assertions;
|
||||||
assertions = assertion;
|
assertions = assertion;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ static uint32_t getRPNByte(uint8_t const **expression, int32_t *size,
|
|||||||
return *(*expression)++;
|
return *(*expression)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct Symbol const *getSymbol(struct Symbol ** const symbolList,
|
static struct Symbol const *getSymbol(struct Symbol const * const *symbolList,
|
||||||
uint32_t index, char const *fileName)
|
uint32_t index, char const *fileName)
|
||||||
{
|
{
|
||||||
struct Symbol const *symbol = symbolList[index];
|
struct Symbol const *symbol = symbolList[index];
|
||||||
@@ -142,7 +142,8 @@ static struct Symbol const *getSymbol(struct Symbol ** const symbolList,
|
|||||||
* @return The patch's value
|
* @return The patch's value
|
||||||
*/
|
*/
|
||||||
static int32_t computeRPNExpr(struct Patch const *patch,
|
static int32_t computeRPNExpr(struct Patch const *patch,
|
||||||
struct Section const *section)
|
struct Section const *section,
|
||||||
|
struct Symbol const * const *fileSymbols)
|
||||||
{
|
{
|
||||||
/* Small shortcut to avoid a lot of repetition */
|
/* Small shortcut to avoid a lot of repetition */
|
||||||
#define popRPN() popRPN(patch->fileName)
|
#define popRPN() popRPN(patch->fileName)
|
||||||
@@ -256,7 +257,7 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
|||||||
value |= getRPNByte(&expression, &size,
|
value |= getRPNByte(&expression, &size,
|
||||||
patch->fileName) << shift;
|
patch->fileName) << shift;
|
||||||
|
|
||||||
value = getSymbol(section->fileSymbols, value,
|
value = getSymbol(fileSymbols, value,
|
||||||
patch->fileName)->section->bank;
|
patch->fileName)->section->bank;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -312,8 +313,7 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
|||||||
value |= getRPNByte(&expression, &size,
|
value |= getRPNByte(&expression, &size,
|
||||||
patch->fileName) << shift;
|
patch->fileName) << shift;
|
||||||
|
|
||||||
symbol = getSymbol(section->fileSymbols, value,
|
symbol = getSymbol(fileSymbols, value, patch->fileName);
|
||||||
patch->fileName);
|
|
||||||
|
|
||||||
if (!strcmp(symbol->name, "@")) {
|
if (!strcmp(symbol->name, "@")) {
|
||||||
value = section->org + patch->offset;
|
value = section->org + patch->offset;
|
||||||
@@ -346,7 +346,9 @@ void patch_CheckAssertions(struct Assertion *assert)
|
|||||||
uint8_t failures = 0;
|
uint8_t failures = 0;
|
||||||
|
|
||||||
while (assert) {
|
while (assert) {
|
||||||
if (!computeRPNExpr(&assert->patch, assert->section)) {
|
if (!computeRPNExpr(&assert->patch, assert->section,
|
||||||
|
(struct Symbol const * const *)
|
||||||
|
assert->fileSymbols)) {
|
||||||
switch ((enum AssertionType)assert->patch.type) {
|
switch ((enum AssertionType)assert->patch.type) {
|
||||||
case ASSERT_FATAL:
|
case ASSERT_FATAL:
|
||||||
errx(1, "%s: %s", assert->patch.fileName,
|
errx(1, "%s: %s", assert->patch.fileName,
|
||||||
@@ -393,7 +395,9 @@ static void applyFilePatches(struct Section *section)
|
|||||||
verbosePrint("Patching section \"%s\"...\n", section->name);
|
verbosePrint("Patching section \"%s\"...\n", section->name);
|
||||||
for (uint32_t patchID = 0; patchID < section->nbPatches; patchID++) {
|
for (uint32_t patchID = 0; patchID < section->nbPatches; patchID++) {
|
||||||
struct Patch *patch = §ion->patches[patchID];
|
struct Patch *patch = §ion->patches[patchID];
|
||||||
int32_t value = computeRPNExpr(patch, section);
|
int32_t value = computeRPNExpr(patch, section,
|
||||||
|
(struct Symbol const * const *)
|
||||||
|
section->fileSymbols);
|
||||||
|
|
||||||
/* `jr` is quite unlike the others... */
|
/* `jr` is quite unlike the others... */
|
||||||
if (patch->type == PATCHTYPE_JR) {
|
if (patch->type == PATCHTYPE_JR) {
|
||||||
|
|||||||
5
test/asm/assert-nosect.asm
Normal file
5
test/asm/assert-nosect.asm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
assert Sym
|
||||||
|
|
||||||
|
SECTION "test", ROM0
|
||||||
|
db 69
|
||||||
|
Sym:
|
||||||
0
test/asm/assert-nosect.err
Normal file
0
test/asm/assert-nosect.err
Normal file
0
test/asm/assert-nosect.out
Normal file
0
test/asm/assert-nosect.out
Normal file
1
test/asm/assert-nosect.out.bin
Normal file
1
test/asm/assert-nosect.out.bin
Normal file
@@ -0,0 +1 @@
|
|||||||
|
E
|
||||||
Reference in New Issue
Block a user