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:
59
preproc.c
59
preproc.c
@@ -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
64
quote.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
2
quote.h
2
quote.h
@@ -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 */
|
||||||
|
17
stdscan.c
17
stdscan.c
@@ -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... */
|
||||||
|
Reference in New Issue
Block a user