Browse Source

Handle infinite recursion in include directives.

master
Ben Kurtovic 9 years ago
parent
commit
5cf943fd7e
2 changed files with 44 additions and 17 deletions
  1. +7
    -7
      src/asm_errors.h
  2. +37
    -10
      src/assembler.c

+ 7
- 7
src/asm_errors.h View File

@@ -6,23 +6,23 @@
/* Enums */ /* Enums */


typedef enum { typedef enum {
ET_SYNTAX,
ET_FILEIO
ET_INCLUDE
} ASMErrorType; } ASMErrorType;


typedef enum { typedef enum {
ED_INCLUDE_BAD_ARG,
ED_BAD_ARG,
ED_RECURSION,
ED_FILE_READ_ERR ED_FILE_READ_ERR
} ASMErrorDesc; } ASMErrorDesc;


/* Strings */ /* Strings */


static const char *asm_error_types[] = { static const char *asm_error_types[] = {
"invalid syntax",
"file I/O"
"include directive"
}; };


static const char *asm_error_descs[] = { static const char *asm_error_descs[] = {
"bad argument passed to include directive",
"couldn't read from file"
"missing or invalid argument",
"infinite recursion detected",
"couldn't read included file"
}; };

+ 37
- 10
src/assembler.c View File

@@ -515,6 +515,7 @@ char* read_include_path(const ASMLine *line)
if (!dup) if (!dup)
OUT_OF_MEMORY() OUT_OF_MEMORY()


// TODO: should normalize filenames in some way to prevent accidental dupes
snprintf(path, maxlen, "%s/%.*s", dirname(dup), (int) (i - start), snprintf(path, maxlen, "%s/%.*s", dirname(dup), (int) (i - start),
line->data + start); line->data + start);
free(dup); free(dup);
@@ -526,6 +527,23 @@ char* read_include_path(const ASMLine *line)
} }


/* /*
Return whether the given path has already been loaded.
*/
static bool path_has_been_loaded(
const char *path, const LineBuffer *root, const ASMInclude *include)
{
if (!strcmp(path, root->filename))
return true;

while (include) {
if (!strcmp(path, include->lines->filename))
return true;
include = include->next;
}
return false;
}

/*
Build a LineBuffer into a ASMLines, normalizing them along the way. Build a LineBuffer into a ASMLines, normalizing them along the way.


This function operates recursively to handle includes, but handles no other This function operates recursively to handle includes, but handles no other
@@ -537,8 +555,8 @@ char* read_include_path(const ASMLine *line)
*includes may be updated in either case. *includes may be updated in either case.
*/ */
static ErrorInfo* build_asm_lines( static ErrorInfo* build_asm_lines(
const LineBuffer *source, ASMLine **head, ASMLine **tail,
ASMInclude **includes)
const LineBuffer *root, const LineBuffer *source, ASMLine **head,
ASMLine **tail, ASMInclude **includes)
{ {
ASMLine dummy = {.next = NULL}; ASMLine dummy = {.next = NULL};
ASMLine *line, *prev = &dummy; ASMLine *line, *prev = &dummy;
@@ -559,17 +577,24 @@ static ErrorInfo* build_asm_lines(
ErrorInfo *ei; ErrorInfo *ei;
char *path = read_include_path(line); char *path = read_include_path(line);
if (!path) { if (!path) {
ei = create_error(line, ET_SYNTAX, ED_INCLUDE_BAD_ARG);
ei = create_error(line, ET_INCLUDE, ED_BAD_ARG);
free_asm_lines(line);
free_asm_lines(dummy.next);
return ei;
}

if (path_has_been_loaded(path, root, *includes)) {
ei = create_error(line, ET_INCLUDE, ED_RECURSION);
free_asm_lines(line); free_asm_lines(line);
free_asm_lines(dummy.next); free_asm_lines(dummy.next);
free(path);
return ei; return ei;
} }


// TODO: handle recursive includes properly
LineBuffer *incbuffer = read_source_file(path, false); LineBuffer *incbuffer = read_source_file(path, false);
free(path); free(path);
if (!incbuffer) { if (!incbuffer) {
ei = create_error(line, ET_FILEIO, ED_FILE_READ_ERR);
ei = create_error(line, ET_INCLUDE, ED_FILE_READ_ERR);
free_asm_lines(line); free_asm_lines(line);
free_asm_lines(dummy.next); free_asm_lines(dummy.next);
return ei; return ei;
@@ -583,16 +608,17 @@ static ErrorInfo* build_asm_lines(
include->next = *includes; include->next = *includes;
*includes = include; *includes = include;


ASMLine *ihead, *itail;
if ((ei = build_asm_lines(incbuffer, &ihead, &itail, includes))) {
ASMLine *inchead, *inctail;
if ((ei = build_asm_lines(root, incbuffer, &inchead, &inctail,
includes))) {
append_to_error(ei, line); append_to_error(ei, line);
free_asm_lines(line); free_asm_lines(line);
free_asm_lines(dummy.next); free_asm_lines(dummy.next);
return ei; return ei;
} }


prev->next = ihead;
prev = itail;
prev->next = inchead;
prev = inctail;
free_asm_lines(line); // Destroy only the .include line free_asm_lines(line); // Destroy only the .include line
} }
else { else {
@@ -634,7 +660,8 @@ static ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source)


ErrorInfo* ei; ErrorInfo* ei;


if ((ei = build_asm_lines(source, &state->lines, NULL, &state->includes)))
if ((ei = build_asm_lines(source, source, &state->lines, NULL,
&state->includes)))
return ei; return ei;


// TODO: iterate here for all global preprocessor directives // TODO: iterate here for all global preprocessor directives


Loading…
Cancel
Save