diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-06-04 11:26:59 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-06-04 11:26:59 -0700 |
commit | 88c9e1f88cd1e67ad4fb2834f3cad6160d5a3fbb (patch) | |
tree | 01b0135d5f68e2e9cb80ccdf774d9f687c33fda2 | |
parent | 0eebf799db452dc1980931bd2f15efde5ecdf28c (diff) | |
download | nasm-88c9e1f88cd1e67ad4fb2834f3cad6160d5a3fbb.tar.gz nasm-88c9e1f88cd1e67ad4fb2834f3cad6160d5a3fbb.tar.bz2 nasm-88c9e1f88cd1e67ad4fb2834f3cad6160d5a3fbb.zip |
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.
-rw-r--r-- | preproc.c | 59 | ||||
-rw-r--r-- | quote.c | 64 | ||||
-rw-r--r-- | quote.h | 2 | ||||
-rw-r--r-- | stdscan.c | 17 |
4 files changed, 83 insertions, 59 deletions
@@ -1144,11 +1144,18 @@ static int ppscan(void *private_data, struct tokenval *tokval) } if (tline->type == TOK_STRING) { + char bq, *ep; + bool errquote; bool rn_warn; size_t l; - l = nasm_unquote(tline->text); - /* TOKEN_ERRNUM if improperly quoted... */ + bq = tline->text[0]; + 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); 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 */ if (t->type == TOK_STRING) { - size_t l1 = nasm_unquote(t->text); - size_t l2 = nasm_unquote(tt->text); + size_t l1 = nasm_unquote(t->text, NULL); + size_t l2 = nasm_unquote(tt->text, NULL); if (l1 != l2) { j = false; @@ -2081,20 +2088,21 @@ static int do_directive(Token * tline) return DIRECTIVE_FOUND; case PP_DEPEND: - tline = expand_smacro(tline->next); - skip_white_(tline); - if (!tline || (tline->type != TOK_STRING && - tline->type != TOK_INTERNAL_STRING)) { + t = tline->next = expand_smacro(tline->next); + skip_white_(t); + if (!t || (t->type != TOK_STRING && + t->type != TOK_INTERNAL_STRING)) { error(ERR_NONFATAL, "`%%depend' expects a file name"); + free_tlist(t); free_tlist(origline); return DIRECTIVE_FOUND; /* but we did _something_ */ } - if (tline->next) + if (t->next) error(ERR_WARNING, "trailing garbage after `%%depend' ignored"); - p = tline->text; - if (tline->type != TOK_INTERNAL_STRING) - nasm_unquote(p); + p = t->text; + if (t->type != TOK_INTERNAL_STRING) + nasm_unquote(p, NULL); if (dephead && !in_list(*dephead, p)) { StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next); sl->next = NULL; @@ -2102,25 +2110,26 @@ static int do_directive(Token * tline) *deptail = sl; deptail = &sl->next; } + free_tlist(t); free_tlist(origline); return DIRECTIVE_FOUND; case PP_INCLUDE: - tline = expand_smacro(tline->next); - skip_white_(tline); + t = tline->next = expand_smacro(tline->next); + skip_white_(t); - if (!tline || (tline->type != TOK_STRING && - tline->type != TOK_INTERNAL_STRING)) { + if (!t || (t->type != TOK_STRING && + t->type != TOK_INTERNAL_STRING)) { error(ERR_NONFATAL, "`%%include' expects a file name"); free_tlist(origline); return DIRECTIVE_FOUND; /* but we did _something_ */ } - if (tline->next) + if (t->next) error(ERR_WARNING, "trailing garbage after `%%include' ignored"); - p = tline->text; - if (tline->type != TOK_INTERNAL_STRING) - nasm_unquote(p); + p = t->text; + if (t->type != TOK_INTERNAL_STRING) + nasm_unquote(p, NULL); inc = nasm_malloc(sizeof(Include)); inc->next = istk; inc->conds = NULL; @@ -2129,7 +2138,7 @@ static int do_directive(Token * tline) /* -MG given but file not found */ nasm_free(inc); } else { - inc->fname = src_set_fname(p); + inc->fname = src_set_fname(nasm_strdup(p)); inc->lineno = src_set_linnum(0); inc->lineinc = 1; inc->expansion = NULL; @@ -2196,7 +2205,7 @@ static int do_directive(Token * tline) skip_white_(tline); if (tok_type_(tline, TOK_STRING)) { p = tline->text; - nasm_unquote(p); + nasm_unquote(p, NULL); expand_macros_in_string(&p); /* WHY? */ error(ERR_NONFATAL, "%s", p); nasm_free(p); @@ -2681,7 +2690,7 @@ static int do_directive(Token * tline) "trailing garbage after `%%pathsearch' ignored"); p = t->text; if (t->type != TOK_INTERNAL_STRING) - nasm_unquote(p); + nasm_unquote(p, NULL); fp = inc_fopen(p, &xsl, &xsl, true); if (fp) { @@ -2742,7 +2751,7 @@ static int do_directive(Token * tline) macro_start = nasm_malloc(sizeof(*macro_start)); 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; /* @@ -2831,7 +2840,7 @@ static int do_directive(Token * tline) a2 = evalresult->value; } - len = nasm_unquote(t->text); + len = nasm_unquote(t->text, NULL); if (a2 < 0) a2 = a2+1+len-a1; if (a1+a2 > (int64_t)len) @@ -183,12 +183,13 @@ static char *emit_utf8(char *q, int32_t v) * * In-place replacement is possible since the unquoted length is always * 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, eq; - char *p, *q, *ep; + char bq; + char *p, *q; char *escp = NULL; char c; enum unq_state { @@ -201,33 +202,42 @@ size_t nasm_unquote(char *str) int ndig = 0; int32_t nval = 0; - bq = str[0]; + p = q = str; + + bq = *p++; if (!bq) return 0; - ln = strlen(str); - eq = str[ln-1]; - if ((bq == '\'' || bq == '\"') && bq == eq) { + switch (bq) { + case '\'': + case '\"': /* '...' or "..." string */ - memmove(str, str+1, ln-2); - str[ln-2] = '\0'; - return ln-2; - } - if (bq == '`' || eq == '`') { + while ((c = *p) && c != bq) { + p++; + *q++ = c; + } + *q = '\0'; + break; + + case '`': /* `...` string */ - q = str; - p = str+1; - ep = str+ln-1; state = st_start; - while (p < ep) { - c = *p++; + while ((c = *p)) { + p++; switch (state) { case st_start: - if (c == '\\') + switch (c) { + case '\\': state = st_backslash; - else + break; + case '`': + p--; + goto out; + default: *q++ = c; + break; + } break; case st_backslash: @@ -357,12 +367,18 @@ size_t nasm_unquote(char *str) *q++ = escp[-1]; break; } - *q = '\0'; - return q-str; + out: + break; + + default: + /* Not a quoted string, just return the input... */ + p = q = strchr(str, '\0'); + break; } - /* Otherwise, just return the input... */ - return ln; + if (ep) + *ep = p; + return q-str; } /* @@ -4,7 +4,7 @@ #include "compiler.h" 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); #endif /* NASM_QUOTE_H */ @@ -47,7 +47,7 @@ static char *stdscan_copy(char *p, int len) char *text; text = nasm_malloc(len + 1); - strncpy(text, p, len); + memcpy(text, p, len); text[len] = '\0'; if (stdscan_templen >= stdscan_tempsize) { @@ -176,15 +176,14 @@ int stdscan(void *private_data, struct tokenval *tv) } } else if (*stdscan_bufptr == '\'' || *stdscan_bufptr == '"' || *stdscan_bufptr == '`') { - /* a char constant */ - char s; + /* a quoted string */ bool rn_warn; - stdscan_bufptr = nasm_skip_string(tv->t_charptr = stdscan_bufptr); - s = *stdscan_bufptr; - tv->t_inttwo = nasm_unquote(tv->t_charptr); - if (!s) - return tv->t_type = TOKEN_ERRNUM; /* unmatched quotes */ - stdscan_bufptr++; /* skip over final quote */ + char start_quote = *stdscan_bufptr; + tv->t_charptr = stdscan_bufptr; + tv->t_inttwo = nasm_unquote(tv->t_charptr, &stdscan_bufptr); + if (*stdscan_bufptr != start_quote) + return tv->t_type = TOKEN_ERRNUM; + stdscan_bufptr++; /* Skip final quote */ tv->t_integer = readstrnum(tv->t_charptr, tv->t_inttwo, &rn_warn); /* Issue: can't readily check rn_warn, because we might be in a db family context... */ |