Merge pull request #177 from AntonioND/an/section-checks

Improve section size checks and buffer handling

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
This commit is contained in:
Antonio Niño Díaz
2017-04-25 13:30:30 +02:00
3 changed files with 109 additions and 45 deletions

View File

@@ -80,8 +80,6 @@
*/ */
#define MAXSECTIONSIZE 0x4000
#define NAME_DB "db" #define NAME_DB "db"
#define NAME_DW "dw" #define NAME_DW "dw"
#define NAME_RB "rb" #define NAME_RB "rb"

View File

@@ -17,8 +17,6 @@
#include "asm/fstack.h" #include "asm/fstack.h"
#include "extern/err.h" #include "extern/err.h"
#define SECTIONCHUNK 0x4000
void out_SetCurrentSection(struct Section * pSect); void out_SetCurrentSection(struct Section * pSect);
struct Patch { struct Patch {
@@ -80,6 +78,24 @@ out_PopSection(void)
fatalerror("No entries in the section stack"); fatalerror("No entries in the section stack");
} }
ULONG
getmaxsectionsize(ULONG secttype, char * sectname)
{
switch (secttype)
{
case SECT_ROM0: return 0x8000; /* If ROMX sections not used. */
case SECT_ROMX: return 0x4000;
case SECT_VRAM: return 0x2000;
case SECT_SRAM: return 0x2000;
case SECT_WRAM0: return 0x2000; /* If WRAMX sections not used. */
case SECT_WRAMX: return 0x1000;
case SECT_OAM: return 0xA0;
case SECT_HRAM: return 0x7F;
default: break;
}
errx(1, "Section \"%s\" has an invalid section type.", sectname);
}
/* /*
* Count the number of symbols used in this object * Count the number of symbols used in this object
*/ */
@@ -441,38 +457,35 @@ checksection(void)
* this much initialized data * this much initialized data
*/ */
void void
checkcodesection(SLONG size) checkcodesection(void)
{ {
checksection(); checksection();
if (pCurrentSection->nType != SECT_ROM0 && if (pCurrentSection->nType != SECT_ROM0 &&
pCurrentSection->nType != SECT_ROMX) { pCurrentSection->nType != SECT_ROMX) {
errx(1, "Section '%s' cannot contain code or data (not a " fatalerror("Section '%s' cannot contain code or data (not ROM0 or ROMX)",
"ROM0 or ROMX)", pCurrentSection->pzName); pCurrentSection->pzName);
} }
if (pCurrentSection->nPC + size > MAXSECTIONSIZE) { }
/*
* N.B.: This check is not sufficient to ensure the section
* will fit, because there can be multiple sections of this
* type. The definitive check must be done at the linking
* stage.
*/
errx(1, "Section '%s' is too big (old size %d + %d > %d)",
pCurrentSection->pzName, pCurrentSection->nPC, size,
MAXSECTIONSIZE);
}
if (((pCurrentSection->nPC % SECTIONCHUNK) >
((pCurrentSection->nPC + size) % SECTIONCHUNK)) &&
(pCurrentSection->nType == SECT_ROM0 ||
pCurrentSection->nType == SECT_ROMX)) {
pCurrentSection->tData = realloc(pCurrentSection->tData,
((pCurrentSection->nPC + size) / SECTIONCHUNK + 1) *
SECTIONCHUNK);
if (pCurrentSection->tData == NULL) { /*
err(1, "Could not expand section"); * Check if the section has grown too much.
} */
void
checksectionoverflow(ULONG delta_size)
{
ULONG maxsize = getmaxsectionsize(pCurrentSection->nType,
pCurrentSection->pzName);
if (pCurrentSection->nPC + delta_size > maxsize) {
/*
* This check is here to trap broken code that generates
* sections that are too big and to prevent the assembler from
* generating huge object files.
* The real check must be done at the linking stage.
*/
fatalerror("Section '%s' is too big (max size = 0x%X bytes).",
pCurrentSection->pzName, maxsize);
} }
return;
} }
/* /*
@@ -580,10 +593,15 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank, SLONG align
pSect->charmap = NULL; pSect->charmap = NULL;
pPatchSymbols = NULL; pPatchSymbols = NULL;
if ((pSect->tData = malloc(SECTIONCHUNK)) != NULL) { pSect->tData = NULL;
return (pSect); if (secttype == SECT_ROM0 || secttype == SECT_ROMX) {
} else /* It is only needed to allocate memory for ROM
fatalerror("Not enough memory for section"); * sections. */
ULONG sectsize = getmaxsectionsize(secttype, pzName);
if ((pSect->tData = malloc(sectsize)) == NULL)
fatalerror("Not enough memory for section");
}
return (pSect);
} else } else
fatalerror("Not enough memory for sectionname"); fatalerror("Not enough memory for sectionname");
} else } else
@@ -641,7 +659,8 @@ out_NewAlignedSection(char *pzName, ULONG secttype, SLONG alignment, SLONG bank)
void void
out_AbsByte(int b) out_AbsByte(int b)
{ {
checkcodesection(1); checkcodesection();
checksectionoverflow(1);
b &= 0xFF; b &= 0xFF;
if (nPass == 2) if (nPass == 2)
pCurrentSection->tData[nPC] = b; pCurrentSection->tData[nPC] = b;
@@ -654,7 +673,8 @@ out_AbsByte(int b)
void void
out_AbsByteGroup(char *s, int length) out_AbsByteGroup(char *s, int length)
{ {
checkcodesection(length); checkcodesection();
checksectionoverflow(length);
while (length--) while (length--)
out_AbsByte(*s++); out_AbsByte(*s++);
} }
@@ -666,13 +686,14 @@ void
out_Skip(int skip) out_Skip(int skip)
{ {
checksection(); checksection();
checksectionoverflow(skip);
if (!((pCurrentSection->nType == SECT_ROM0) if (!((pCurrentSection->nType == SECT_ROM0)
|| (pCurrentSection->nType == SECT_ROMX))) { || (pCurrentSection->nType == SECT_ROMX))) {
pCurrentSection->nPC += skip; pCurrentSection->nPC += skip;
nPC += skip; nPC += skip;
pPCSymbol->nValue += skip; pPCSymbol->nValue += skip;
} else { } else {
checkcodesection(skip); checkcodesection();
while (skip--) while (skip--)
out_AbsByte(CurrentOptions.fillchar); out_AbsByte(CurrentOptions.fillchar);
} }
@@ -684,7 +705,8 @@ out_Skip(int skip)
void void
out_String(char *s) out_String(char *s)
{ {
checkcodesection(strlen(s)); checkcodesection();
checksectionoverflow(strlen(s));
while (*s) while (*s)
out_AbsByte(*s++); out_AbsByte(*s++);
} }
@@ -697,7 +719,8 @@ out_String(char *s)
void void
out_RelByte(struct Expression * expr) out_RelByte(struct Expression * expr)
{ {
checkcodesection(1); checkcodesection();
checksectionoverflow(1);
if (rpn_isReloc(expr)) { if (rpn_isReloc(expr)) {
if (nPass == 2) { if (nPass == 2) {
pCurrentSection->tData[nPC] = 0; pCurrentSection->tData[nPC] = 0;
@@ -718,7 +741,8 @@ out_RelByte(struct Expression * expr)
void void
out_AbsWord(int b) out_AbsWord(int b)
{ {
checkcodesection(2); checkcodesection();
checksectionoverflow(2);
b &= 0xFFFF; b &= 0xFFFF;
if (nPass == 2) { if (nPass == 2) {
pCurrentSection->tData[nPC] = b & 0xFF; pCurrentSection->tData[nPC] = b & 0xFF;
@@ -738,7 +762,8 @@ out_RelWord(struct Expression * expr)
{ {
ULONG b; ULONG b;
checkcodesection(2); checkcodesection();
checksectionoverflow(2);
b = expr->nVal & 0xFFFF; b = expr->nVal & 0xFFFF;
if (rpn_isReloc(expr)) { if (rpn_isReloc(expr)) {
if (nPass == 2) { if (nPass == 2) {
@@ -760,7 +785,8 @@ out_RelWord(struct Expression * expr)
void void
out_AbsLong(SLONG b) out_AbsLong(SLONG b)
{ {
checkcodesection(sizeof(SLONG)); checkcodesection();
checksectionoverflow(sizeof(SLONG));
if (nPass == 2) { if (nPass == 2) {
pCurrentSection->tData[nPC] = b & 0xFF; pCurrentSection->tData[nPC] = b & 0xFF;
pCurrentSection->tData[nPC + 1] = b >> 8; pCurrentSection->tData[nPC + 1] = b >> 8;
@@ -781,7 +807,8 @@ out_RelLong(struct Expression * expr)
{ {
SLONG b; SLONG b;
checkcodesection(4); checkcodesection();
checksectionoverflow(4);
b = expr->nVal; b = expr->nVal;
if (rpn_isReloc(expr)) { if (rpn_isReloc(expr)) {
if (nPass == 2) { if (nPass == 2) {
@@ -807,7 +834,8 @@ out_PCRelByte(struct Expression * expr)
{ {
SLONG b = expr->nVal; SLONG b = expr->nVal;
checkcodesection(1); checkcodesection();
checksectionoverflow(1);
b = (b & 0xFFFF) - (nPC + 1); b = (b & 0xFFFF) - (nPC + 1);
if (nPass == 2 && (b < -128 || b > 127)) if (nPass == 2 && (b < -128 || b > 127))
yyerror("PC-relative value must be 8-bit"); yyerror("PC-relative value must be 8-bit");
@@ -835,7 +863,8 @@ out_BinaryFile(char *s)
fsize = ftell(f); fsize = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
checkcodesection(fsize); checkcodesection();
checksectionoverflow(fsize);
if (nPass == 2) { if (nPass == 2) {
SLONG dest = nPC; SLONG dest = nPC;
@@ -879,7 +908,8 @@ out_BinaryFileSlice(char *s, SLONG start_pos, SLONG length)
fseek(f, start_pos, SEEK_SET); fseek(f, start_pos, SEEK_SET);
checkcodesection(length); checkcodesection();
checksectionoverflow(length);
if (nPass == 2) { if (nPass == 2) {
SLONG dest = nPC; SLONG dest = nPC;

View File

@@ -169,6 +169,42 @@ obj_ReadRGBSection(FILE * f)
} }
} }
unsigned int maxsize = 0;
/* Verify that the section isn't too big */
switch (pSection->Type)
{
case SECT_ROM0:
maxsize = (options & OPT_TINY) ? 0x8000 : 0x4000;
break;
case SECT_ROMX:
maxsize = 0x4000;
break;
case SECT_VRAM:
case SECT_SRAM:
maxsize = 0x2000;
break;
case SECT_WRAM0:
maxsize = (options & OPT_CONTWRAM) ? 0x2000 : 0x1000;
break;
case SECT_WRAMX:
maxsize = 0x1000;
break;
case SECT_OAM:
maxsize = 0xA0;
break;
case SECT_HRAM:
maxsize = 0x7F;
break;
default:
errx(1, "Section \"%s\" has an invalid section type.", pzName);
break;
}
if (pSection->nByteSize > maxsize) {
errx(1, "Section \"%s\" is bigger than the max size for that type: 0x%X > 0x%X",
pzName, pSection->nByteSize, maxsize);
}
if ((pSection->Type == SECT_ROMX) || (pSection->Type == SECT_ROM0)) { if ((pSection->Type == SECT_ROMX) || (pSection->Type == SECT_ROM0)) {
/* /*
* These sectiontypes contain data... * These sectiontypes contain data...