From 8e716325366e3dd9d3417c824d74fe5072fd0ac8 Mon Sep 17 00:00:00 2001 From: Lorenzooone Date: Mon, 14 Aug 2023 18:12:00 +0200 Subject: [PATCH] Fix segfaults at EOF for scan_includes, and add token/newline checks (#1068) --- tools/scan_includes.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/tools/scan_includes.c b/tools/scan_includes.c index e57ddc358..826af56cc 100644 --- a/tools/scan_includes.c +++ b/tools/scan_includes.c @@ -42,29 +42,48 @@ void scan_file(const char *filename, bool strict) { for (char *ptr = contents; ptr && ptr - contents < size; ptr++) { bool is_incbin = false, is_include = false; + ptr = strpbrk(ptr, ";\"Ii"); + if (!ptr) { + break; + } switch (*ptr) { case ';': - ptr = strchr(ptr, '\n'); + // Skip comments until the end of the line + ptr = strchr(ptr + 1, '\n'); if (!ptr) { fprintf(stderr, "%s: no newline at end of file\n", filename); + goto done; } break; case '"': - ptr++; - ptr = strchr(ptr, '"'); + // Skip string iteral until the closing quote + ptr = strchr(ptr + 1, '"'); if (ptr) { ptr++; } else { fprintf(stderr, "%s: unterminated string\n", filename); + goto done; } break; case 'I': case 'i': + /* empty statement between the label and the variable declaration */; + // Check that an INCLUDE/INCBIN starts as its own token + char before = ptr > contents ? *(ptr - 1) : '\n'; + if (before != ' ' && before != '\t' && before != '\n' && before != ':') { + break; + } is_incbin = !strncmp(ptr, "INCBIN", 6) || !strncmp(ptr, "incbin", 6); is_include = !strncmp(ptr, "INCLUDE", 7) || !strncmp(ptr, "include", 7); if (is_incbin || is_include) { - ptr = strchr(ptr, '"'); - if (ptr) { + // Check that an INCLUDE/INCBIN ends as its own token + ptr += is_include ? 7 : 6; + if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n' && *ptr != '"') { + break; + } + ptr += strspn(ptr, " \t"); + if (*ptr == '"') { + // Print the file path and recursively scan INCLUDEs ptr++; char *include_path = ptr; size_t length = strcspn(ptr, "\""); @@ -74,12 +93,19 @@ void scan_file(const char *filename, bool strict) { if (is_include) { scan_file(include_path, strict); } + } else { + fprintf(stderr, "%s: no file path after INC%s\n", filename, is_include ? "LUDE" : "BIN"); + // Continue to process a comment + if (*ptr == ';') { + ptr--; + } } } break; } } +done: free(contents); }