ref: 45b6872e2ad5374c146d1ddca61487976ba65f84
parent: 056109652d78701062ff0bb925a07c2c6ad33a2c
author: Anthony J. Bentley <[email protected]>
date: Tue Sep 23 20:23:40 EDT 2014
rgbasm: Fix TOCTOU and reduce buffering.
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,9 @@
src/asm/output.o \
src/asm/rpn.o \
src/asm/symbol.o \
- src/asm/gameboy/locallex.o
+ src/asm/gameboy/locallex.o \
+ src/extern/strlcpy.o \
+ src/extern/strlcat.o
rgblib_obj := \
src/lib/library.o \
--- a/include/asm/fstack.h
+++ b/include/asm/fstack.h
@@ -9,6 +9,8 @@
#ifndef ASMOTOR_ASM_FSTACK_H
#define ASMOTOR_ASM_FSTACK_H
+#include <stdio.h>
+
#include "asm/asm.h"
#include "asm/types.h"
#include "asm/lexer.h"
@@ -27,14 +29,17 @@
ULONG nREPTBlockSize;
};
-extern ULONG fstk_RunInclude(char *s);
+void
+fstk_RunInclude(char *);
extern void fstk_RunMacroArg(SLONG s);
-extern ULONG fstk_Init(char *s);
+void
+fstk_Init(char *);
extern void fstk_Dump(void);
extern void fstk_AddIncludePath(char *s);
extern ULONG fstk_RunMacro(char *s);
extern void fstk_RunRept(ULONG count);
-extern void fstk_FindFile(char *s);
+FILE *
+fstk_FindFile(char *);
extern int yywrap(void);
--- a/src/asm/fstack.c
+++ b/src/asm/fstack.c
@@ -5,10 +5,19 @@
*
*/
+#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifndef STRL_IN_LIBC
+#define strlcpy rgbds_strlcpy
+#define strlcat rgbds_strlcat
+size_t strlcpy(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
+#endif
+
#include "asm/symbol.h"
#include "asm/fstack.h"
#include "asm/types.h"
@@ -195,28 +204,33 @@
strcpy(IncludePaths[NextIncPath++], s);
}
-void
-fstk_FindFile(char *s)
+FILE *
+fstk_FindFile(char *fname)
{
- char t[_MAX_PATH + 1];
- SLONG i = -1;
+ char path[PATH_MAX];
+ int i;
+ FILE *f;
- strcpy(t, s);
+ if ((f = fopen(fname, "rb")) != NULL || errno != ENOENT) {
+ return f;
+ }
- while (i < NextIncPath) {
- FILE *f;
-
- if ((f = fopen(t, "rb")) != NULL) {
- fclose(f);
- strcpy(s, t);
- return;
+ for (i = 0; i < NextIncPath; ++i) {
+ if (strlcpy(path, IncludePaths[i], sizeof path) >=
+ sizeof path) {
+ continue;
}
- i += 1;
- if (i < NextIncPath) {
- strcpy(t, IncludePaths[i]);
- strcat(t, s);
+ if (strlcat(path, fname, sizeof path) >= sizeof path) {
+ continue;
}
+
+ if ((f = fopen(path, "rb")) != NULL || errno != ENOENT) {
+ return f;
+ }
}
+
+ errno = ENOENT;
+ return NULL;
}
/*
* RGBAsm - FSTACK.C (FileStack routines)
@@ -225,33 +239,32 @@
*
*/
-ULONG
+void
fstk_RunInclude(char *tzFileName)
{
FILE *f;
- //printf("INCLUDE: %s\n", s);
+ f = fstk_FindFile(tzFileName);
- fstk_FindFile(tzFileName);
- //printf("INCLUDING: %s\n", tzFileName);
+ if (f == NULL) {
+ fprintf(stderr, "Unable to open included file '%s': ",
+ tzFileName);
+ perror(NULL);
+ exit(1);
+ }
- if ((f = fopen(tzFileName, "r")) != NULL) {
- pushcontext();
- nLineNo = 1;
- nCurrentStatus = STAT_isInclude;
- strcpy(tzCurrentFileName, tzFileName);
- pCurrentFile = f;
- CurrentFlexHandle = yy_create_buffer(pCurrentFile);
- yy_switch_to_buffer(CurrentFlexHandle);
+ pushcontext();
+ nLineNo = 1;
+ nCurrentStatus = STAT_isInclude;
+ strcpy(tzCurrentFileName, tzFileName);
+ pCurrentFile = f;
+ CurrentFlexHandle = yy_create_buffer(pCurrentFile);
+ yy_switch_to_buffer(CurrentFlexHandle);
- //Dirty hack to give the INCLUDE directive a linefeed
+ //Dirty hack to give the INCLUDE directive a linefeed
- yyunput('\n');
- nLineNo -= 1;
-
- return (1);
- } else
- return (0);
+ yyunput('\n');
+ nLineNo -= 1;
}
/*
* RGBAsm - FSTACK.C (FileStack routines)
@@ -360,7 +373,7 @@
*
*/
-ULONG
+void
fstk_Init(char *s)
{
char tzFileName[_MAX_PATH + 1];
@@ -368,17 +381,19 @@
sym_AddString("__FILE__", s);
strcpy(tzFileName, s);
- fstk_FindFile(tzFileName);
-
pFileStack = NULL;
- if ((pCurrentFile = fopen(tzFileName, "r")) != NULL) {
- nMacroCount = 0;
- nCurrentStatus = STAT_isInclude;
- strcpy(tzCurrentFileName, tzFileName);
- CurrentFlexHandle = yy_create_buffer(pCurrentFile);
- yy_switch_to_buffer(CurrentFlexHandle);
- nLineNo = 1;
- return (1);
- } else
- return (0);
+ pCurrentFile = fopen(tzFileName, "rb");
+ if (pCurrentFile == NULL) {
+ fprintf(stderr, "Unable to open file '%s': ",
+ tzFileName);
+ perror(NULL);
+ exit(1);
+ }
+
+ nMacroCount = 0;
+ nCurrentStatus = STAT_isInclude;
+ strcpy(tzCurrentFileName, tzFileName);
+ CurrentFlexHandle = yy_create_buffer(pCurrentFile);
+ yy_switch_to_buffer(CurrentFlexHandle);
+ nLineNo = 1;
}
--- a/src/asm/main.c
+++ b/src/asm/main.c
@@ -348,7 +348,6 @@
DefaultOptions = CurrentOptions;
- /* tzMainfile=argv[argn++]; argc-=1; */
tzMainfile = argv[argc - 1];
setuplex();
@@ -366,75 +365,71 @@
nPass = 1;
nErrors = 0;
sym_PrepPass1();
- if (fstk_Init(tzMainfile)) {
- if (CurrentOptions.verbose) {
- printf("Pass 1...\n");
- }
+ fstk_Init(tzMainfile);
+ if (CurrentOptions.verbose) {
+ printf("Pass 1...\n");
+ }
- yy_set_state(LEX_STATE_NORMAL);
- opt_SetCurrentOptions(&DefaultOptions);
+ yy_set_state(LEX_STATE_NORMAL);
+ opt_SetCurrentOptions(&DefaultOptions);
- if (yyparse() == 0 && nErrors == 0) {
- if (nIFDepth == 0) {
- nTotalLines = 0;
- nLineNo = 1;
- nIFDepth = 0;
- nPC = 0;
- nPass = 2;
- nErrors = 0;
- sym_PrepPass2();
- out_PrepPass2();
- fstk_Init(tzMainfile);
- yy_set_state(LEX_STATE_NORMAL);
- opt_SetCurrentOptions(&DefaultOptions);
+ if (yyparse() == 0 && nErrors == 0) {
+ if (nIFDepth == 0) {
+ nTotalLines = 0;
+ nLineNo = 1;
+ nIFDepth = 0;
+ nPC = 0;
+ nPass = 2;
+ nErrors = 0;
+ sym_PrepPass2();
+ out_PrepPass2();
+ fstk_Init(tzMainfile);
+ yy_set_state(LEX_STATE_NORMAL);
+ opt_SetCurrentOptions(&DefaultOptions);
- if (CurrentOptions.verbose) {
- printf("Pass 2...\n");
- }
+ if (CurrentOptions.verbose) {
+ printf("Pass 2...\n");
+ }
- if (yyparse() == 0 && nErrors == 0) {
- double timespent;
+ if (yyparse() == 0 && nErrors == 0) {
+ double timespent;
- nEndClock = clock();
- timespent =
- ((double) (nEndClock - nStartClock))
- / (double) CLOCKS_PER_SEC;
- if (CurrentOptions.verbose) {
- printf
- ("Success! %ld lines in %d.%02d seconds ",
- nTotalLines, (int) timespent,
- ((int) (timespent * 100.0)) % 100);
- if (timespent == 0)
- printf
- ("(INFINITY lines/minute)\n");
- else
- printf("(%d lines/minute)\n",
- (int) (60 / timespent *
- nTotalLines));
- }
- out_WriteObject();
- } else {
+ nEndClock = clock();
+ timespent =
+ ((double) (nEndClock - nStartClock))
+ / (double) CLOCKS_PER_SEC;
+ if (CurrentOptions.verbose) {
printf
- ("Assembly aborted in pass 2 (%ld errors)!\n",
- nErrors);
- //sym_PrintSymbolTable();
- exit(5);
+ ("Success! %ld lines in %d.%02d seconds ",
+ nTotalLines, (int) timespent,
+ ((int) (timespent * 100.0)) % 100);
+ if (timespent == 0)
+ printf
+ ("(INFINITY lines/minute)\n");
+ else
+ printf("(%d lines/minute)\n",
+ (int) (60 / timespent *
+ nTotalLines));
}
+ out_WriteObject();
} else {
- fprintf(stderr,
- "Unterminated IF construct (%ld levels)!\n",
- nIFDepth);
- exit(1);
+ printf
+ ("Assembly aborted in pass 2 (%ld errors)!\n",
+ nErrors);
+ //sym_PrintSymbolTable();
+ exit(5);
}
} else {
fprintf(stderr,
- "Assembly aborted in pass 1 (%ld errors)!\n",
- nErrors);
+ "Unterminated IF construct (%ld levels)!\n",
+ nIFDepth);
exit(1);
}
} else {
- printf("File '%s' not found\n", tzMainfile);
- exit(5);
+ fprintf(stderr,
+ "Assembly aborted in pass 1 (%ld errors)!\n",
+ nErrors);
+ exit(1);
}
- return (0);
+ return 0;
}
--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -907,30 +907,33 @@
{
FILE *f;
- fstk_FindFile(s);
+ f = fstk_FindFile(s);
+ if (f == NULL) {
+ fprintf(stderr, "Unable to open incbin file '%s': ",
+ s);
+ perror(NULL);
+ exit(1);
+ }
- if ((f = fopen(s, "rb")) != NULL) {
- SLONG fsize;
+ SLONG fsize;
- fseek(f, 0, SEEK_END);
- fsize = ftell(f);
- fseek(f, 0, SEEK_SET);
+ fseek(f, 0, SEEK_END);
+ fsize = ftell(f);
+ fseek(f, 0, SEEK_SET);
- checkcodesection(fsize);
+ checkcodesection(fsize);
- if (nPass == 2) {
- SLONG dest = nPC;
- SLONG todo = fsize;
+ if (nPass == 2) {
+ SLONG dest = nPC;
+ SLONG todo = fsize;
- while (todo--)
- pCurrentSection->tData[dest++] = fgetc(f);
- }
- pCurrentSection->nPC += fsize;
- nPC += fsize;
- pPCSymbol->nValue += fsize;
- fclose(f);
- } else
- fatalerror("Could not open file '%s': %s", s, strerror(errno));
+ while (todo--)
+ pCurrentSection->tData[dest++] = fgetc(f);
+ }
+ pCurrentSection->nPC += fsize;
+ nPC += fsize;
+ pPCSymbol->nValue += fsize;
+ fclose(f);
}
void
@@ -944,36 +947,39 @@
if (length < 0)
fatalerror("Number of bytes to read must be greater than zero");
- fstk_FindFile(s);
+ f = fstk_FindFile(s);
+ if (f == NULL) {
+ fprintf(stderr, "Unable to open included file '%s': ",
+ s);
+ perror(NULL);
+ exit(1);
+ }
- if ((f = fopen(s, "rb")) != NULL) {
- SLONG fsize;
+ SLONG fsize;
- fseek(f, 0, SEEK_END);
- fsize = ftell(f);
+ fseek(f, 0, SEEK_END);
+ fsize = ftell(f);
- if (start_pos >= fsize)
- fatalerror("Specified start position is greater than length of file");
+ if (start_pos >= fsize)
+ fatalerror("Specified start position is greater than length of file");
- if ((start_pos + length) > fsize)
- fatalerror("Specified range in INCBIN is out of bounds");
+ if ((start_pos + length) > fsize)
+ fatalerror("Specified range in INCBIN is out of bounds");
- fseek(f, start_pos, SEEK_SET);
+ fseek(f, start_pos, SEEK_SET);
- checkcodesection(length);
+ checkcodesection(length);
- if (nPass == 2) {
- SLONG dest = nPC;
- SLONG todo = length;
+ if (nPass == 2) {
+ SLONG dest = nPC;
+ SLONG todo = length;
- while (todo--)
- pCurrentSection->tData[dest++] = fgetc(f);
- }
- pCurrentSection->nPC += length;
- nPC += length;
- pPCSymbol->nValue += length;
+ while (todo--)
+ pCurrentSection->tData[dest++] = fgetc(f);
+ }
+ pCurrentSection->nPC += length;
+ nPC += length;
+ pPCSymbol->nValue += length;
- fclose(f);
- } else
- fatalerror("Could not open file '%s': %s", s, strerror(errno));
+ fclose(f);
}
--- a/src/asm/yaccprt3.y
+++ b/src/asm/yaccprt3.y
@@ -265,10 +265,7 @@
include : T_POP_INCLUDE string
{
- if( !fstk_RunInclude($2) )
- {
- yyerror("Could not open file '%s' : %s\n", $2, strerror(errno));
- }
+ fstk_RunInclude($2);
}
;
--- /dev/null
+++ b/src/extern/strlcat.c
@@ -1,0 +1,55 @@
+/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+rgbds_strlcat(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
--- /dev/null
+++ b/src/extern/strlcpy.c
@@ -1,0 +1,51 @@
+/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+rgbds_strlcpy(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0) {
+ while (--n != 0) {
+ if ((*d++ = *s++) == '\0')
+ break;
+ }
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}