0
0
mirror of https://github.com/netwide-assembler/nasm.git synced 2025-09-22 10:43:39 -04:00

Fix memory management issues with expanded %include

Ownership of the filename string was a bit fuzzy, with the result that
we were freeing it even though it was retained for use by __FILE__.
Clean up a number of other memory management issues with the new
quoting code, and change the stdscan implementation to one pass over
the string.
This commit is contained in:
H. Peter Anvin
2008-06-04 11:26:59 -07:00
parent 0eebf799db
commit 88c9e1f88c
4 changed files with 83 additions and 59 deletions

View File

@@ -1144,11 +1144,18 @@ static int ppscan(void *private_data, struct tokenval *tokval)
} }
if (tline->type == TOK_STRING) { if (tline->type == TOK_STRING) {
char bq, *ep;
bool errquote;
bool rn_warn; bool rn_warn;
size_t l; size_t l;
l = nasm_unquote(tline->text); bq = tline->text[0];
/* TOKEN_ERRNUM if improperly quoted... */ l = nasm_unquote(tline->text, &ep);
if (ep[0] != bq || ep[1] != '\0')
errquote = true;
if (errquote)
return tokval->t_type = TOKEN_ERRNUM;
tokval->t_integer = readstrnum(tline->text, l, &rn_warn); tokval->t_integer = readstrnum(tline->text, l, &rn_warn);
if (rn_warn) if (rn_warn)
@@ -1520,8 +1527,8 @@ static bool if_condition(Token * tline, enum preproc_token ct)
} }
/* When comparing strings, need to unquote them first */ /* When comparing strings, need to unquote them first */
if (t->type == TOK_STRING) { if (t->type == TOK_STRING) {
size_t l1 = nasm_unquote(t->text); size_t l1 = nasm_unquote(t->text, NULL);
size_t l2 = nasm_unquote(tt->text); size_t l2 = nasm_unquote(tt->text, NULL);
if (l1 != l2) { if (l1 != l2) {
j = false; j = false;
@@ -2081,20 +2088,21 @@ static int do_directive(Token * tline)
return DIRECTIVE_FOUND; return DIRECTIVE_FOUND;
case PP_DEPEND: case PP_DEPEND:
tline = expand_smacro(tline->next); t = tline->next = expand_smacro(tline->next);
skip_white_(tline); skip_white_(t);
if (!tline || (tline->type != TOK_STRING && if (!t || (t->type != TOK_STRING &&
tline->type != TOK_INTERNAL_STRING)) { t->type != TOK_INTERNAL_STRING)) {
error(ERR_NONFATAL, "`%%depend' expects a file name"); error(ERR_NONFATAL, "`%%depend' expects a file name");
free_tlist(t);
free_tlist(origline); free_tlist(origline);
return DIRECTIVE_FOUND; /* but we did _something_ */ return DIRECTIVE_FOUND; /* but we did _something_ */
} }
if (tline->next) if (t->next)
error(ERR_WARNING, error(ERR_WARNING,
"trailing garbage after `%%depend' ignored"); "trailing garbage after `%%depend' ignored");
p = tline->text; p = t->text;
if (tline->type != TOK_INTERNAL_STRING) if (t->type != TOK_INTERNAL_STRING)
nasm_unquote(p); nasm_unquote(p, NULL);
if (dephead && !in_list(*dephead, p)) { if (dephead && !in_list(*dephead, p)) {
StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next); StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
sl->next = NULL; sl->next = NULL;
@@ -2102,25 +2110,26 @@ static int do_directive(Token * tline)
*deptail = sl; *deptail = sl;
deptail = &sl->next; deptail = &sl->next;
} }
free_tlist(t);
free_tlist(origline); free_tlist(origline);
return DIRECTIVE_FOUND; return DIRECTIVE_FOUND;
case PP_INCLUDE: case PP_INCLUDE:
tline = expand_smacro(tline->next); t = tline->next = expand_smacro(tline->next);
skip_white_(tline); skip_white_(t);
if (!tline || (tline->type != TOK_STRING && if (!t || (t->type != TOK_STRING &&
tline->type != TOK_INTERNAL_STRING)) { t->type != TOK_INTERNAL_STRING)) {
error(ERR_NONFATAL, "`%%include' expects a file name"); error(ERR_NONFATAL, "`%%include' expects a file name");
free_tlist(origline); free_tlist(origline);
return DIRECTIVE_FOUND; /* but we did _something_ */ return DIRECTIVE_FOUND; /* but we did _something_ */
} }
if (tline->next) if (t->next)
error(ERR_WARNING, error(ERR_WARNING,
"trailing garbage after `%%include' ignored"); "trailing garbage after `%%include' ignored");
p = tline->text; p = t->text;
if (tline->type != TOK_INTERNAL_STRING) if (t->type != TOK_INTERNAL_STRING)
nasm_unquote(p); nasm_unquote(p, NULL);
inc = nasm_malloc(sizeof(Include)); inc = nasm_malloc(sizeof(Include));
inc->next = istk; inc->next = istk;
inc->conds = NULL; inc->conds = NULL;
@@ -2129,7 +2138,7 @@ static int do_directive(Token * tline)
/* -MG given but file not found */ /* -MG given but file not found */
nasm_free(inc); nasm_free(inc);
} else { } else {
inc->fname = src_set_fname(p); inc->fname = src_set_fname(nasm_strdup(p));
inc->lineno = src_set_linnum(0); inc->lineno = src_set_linnum(0);
inc->lineinc = 1; inc->lineinc = 1;
inc->expansion = NULL; inc->expansion = NULL;
@@ -2196,7 +2205,7 @@ static int do_directive(Token * tline)
skip_white_(tline); skip_white_(tline);
if (tok_type_(tline, TOK_STRING)) { if (tok_type_(tline, TOK_STRING)) {
p = tline->text; p = tline->text;
nasm_unquote(p); nasm_unquote(p, NULL);
expand_macros_in_string(&p); /* WHY? */ expand_macros_in_string(&p); /* WHY? */
error(ERR_NONFATAL, "%s", p); error(ERR_NONFATAL, "%s", p);
nasm_free(p); nasm_free(p);
@@ -2681,7 +2690,7 @@ static int do_directive(Token * tline)
"trailing garbage after `%%pathsearch' ignored"); "trailing garbage after `%%pathsearch' ignored");
p = t->text; p = t->text;
if (t->type != TOK_INTERNAL_STRING) if (t->type != TOK_INTERNAL_STRING)
nasm_unquote(p); nasm_unquote(p, NULL);
fp = inc_fopen(p, &xsl, &xsl, true); fp = inc_fopen(p, &xsl, &xsl, true);
if (fp) { if (fp) {
@@ -2742,7 +2751,7 @@ static int do_directive(Token * tline)
macro_start = nasm_malloc(sizeof(*macro_start)); macro_start = nasm_malloc(sizeof(*macro_start));
macro_start->next = NULL; macro_start->next = NULL;
make_tok_num(macro_start, nasm_unquote(t->text)); make_tok_num(macro_start, nasm_unquote(t->text, NULL));
macro_start->mac = NULL; macro_start->mac = NULL;
/* /*
@@ -2831,7 +2840,7 @@ static int do_directive(Token * tline)
a2 = evalresult->value; a2 = evalresult->value;
} }
len = nasm_unquote(t->text); len = nasm_unquote(t->text, NULL);
if (a2 < 0) if (a2 < 0)
a2 = a2+1+len-a1; a2 = a2+1+len-a1;
if (a1+a2 > (int64_t)len) if (a1+a2 > (int64_t)len)

64
quote.c
View File

@@ -183,12 +183,13 @@ static char *emit_utf8(char *q, int32_t v)
* *
* In-place replacement is possible since the unquoted length is always * In-place replacement is possible since the unquoted length is always
* shorter than or equal to the quoted length. * shorter than or equal to the quoted length.
*
* *ep points to the final quote, or to the null if improperly quoted.
*/ */
size_t nasm_unquote(char *str) size_t nasm_unquote(char *str, char **ep)
{ {
size_t ln; char bq;
char bq, eq; char *p, *q;
char *p, *q, *ep;
char *escp = NULL; char *escp = NULL;
char c; char c;
enum unq_state { enum unq_state {
@@ -201,33 +202,42 @@ size_t nasm_unquote(char *str)
int ndig = 0; int ndig = 0;
int32_t nval = 0; int32_t nval = 0;
bq = str[0]; p = q = str;
bq = *p++;
if (!bq) if (!bq)
return 0; return 0;
ln = strlen(str);
eq = str[ln-1];
if ((bq == '\'' || bq == '\"') && bq == eq) { switch (bq) {
case '\'':
case '\"':
/* '...' or "..." string */ /* '...' or "..." string */
memmove(str, str+1, ln-2); while ((c = *p) && c != bq) {
str[ln-2] = '\0'; p++;
return ln-2; *q++ = c;
} }
if (bq == '`' || eq == '`') { *q = '\0';
break;
case '`':
/* `...` string */ /* `...` string */
q = str;
p = str+1;
ep = str+ln-1;
state = st_start; state = st_start;
while (p < ep) { while ((c = *p)) {
c = *p++; p++;
switch (state) { switch (state) {
case st_start: case st_start:
if (c == '\\') switch (c) {
case '\\':
state = st_backslash; state = st_backslash;
else break;
case '`':
p--;
goto out;
default:
*q++ = c; *q++ = c;
break;
}
break; break;
case st_backslash: case st_backslash:
@@ -357,12 +367,18 @@ size_t nasm_unquote(char *str)
*q++ = escp[-1]; *q++ = escp[-1];
break; break;
} }
*q = '\0'; out:
return q-str; break;
default:
/* Not a quoted string, just return the input... */
p = q = strchr(str, '\0');
break;
} }
/* Otherwise, just return the input... */ if (ep)
return ln; *ep = p;
return q-str;
} }
/* /*

View File

@@ -4,7 +4,7 @@
#include "compiler.h" #include "compiler.h"
char *nasm_quote(char *str, size_t len); char *nasm_quote(char *str, size_t len);
size_t nasm_unquote(char *str); size_t nasm_unquote(char *str, char **endptr);
char *nasm_skip_string(char *str); char *nasm_skip_string(char *str);
#endif /* NASM_QUOTE_H */ #endif /* NASM_QUOTE_H */

View File

@@ -47,7 +47,7 @@ static char *stdscan_copy(char *p, int len)
char *text; char *text;
text = nasm_malloc(len + 1); text = nasm_malloc(len + 1);
strncpy(text, p, len); memcpy(text, p, len);
text[len] = '\0'; text[len] = '\0';
if (stdscan_templen >= stdscan_tempsize) { if (stdscan_templen >= stdscan_tempsize) {
@@ -176,15 +176,14 @@ int stdscan(void *private_data, struct tokenval *tv)
} }
} else if (*stdscan_bufptr == '\'' || *stdscan_bufptr == '"' || } else if (*stdscan_bufptr == '\'' || *stdscan_bufptr == '"' ||
*stdscan_bufptr == '`') { *stdscan_bufptr == '`') {
/* a char constant */ /* a quoted string */
char s;
bool rn_warn; bool rn_warn;
stdscan_bufptr = nasm_skip_string(tv->t_charptr = stdscan_bufptr); char start_quote = *stdscan_bufptr;
s = *stdscan_bufptr; tv->t_charptr = stdscan_bufptr;
tv->t_inttwo = nasm_unquote(tv->t_charptr); tv->t_inttwo = nasm_unquote(tv->t_charptr, &stdscan_bufptr);
if (!s) if (*stdscan_bufptr != start_quote)
return tv->t_type = TOKEN_ERRNUM; /* unmatched quotes */ return tv->t_type = TOKEN_ERRNUM;
stdscan_bufptr++; /* skip over final quote */ stdscan_bufptr++; /* Skip final quote */
tv->t_integer = readstrnum(tv->t_charptr, tv->t_inttwo, &rn_warn); tv->t_integer = readstrnum(tv->t_charptr, tv->t_inttwo, &rn_warn);
/* Issue: can't readily check rn_warn, because we might be in /* Issue: can't readily check rn_warn, because we might be in
a db family context... */ a db family context... */