0
0
mirror of https://github.com/netwide-assembler/nasm.git synced 2025-11-08 23:27:15 -05:00

directives: correctly handle quoted strings in directives

Quoted strings should be valid inside directives, including ones that
contain a ] character. Also check for garbage on the line after the
directive.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel)
2025-10-10 10:41:09 -07:00
parent 5a6b276b89
commit c0aec6969b
3 changed files with 81 additions and 37 deletions

View File

@@ -22,6 +22,7 @@
#include "listing.h" #include "listing.h"
#include "labels.h" #include "labels.h"
#include "iflag.h" #include "iflag.h"
#include "quote.h"
struct cpunames { struct cpunames {
const char *name; const char *name;
@@ -178,34 +179,51 @@ static int get_bits(const char *value)
static enum directive parse_directive_line(char **directive, char **value) static enum directive parse_directive_line(char **directive, char **value)
{ {
char *p, *q, *buf; char *p, *q, *eol, *buf;
char c;
buf = nasm_skip_spaces(*directive); buf = nasm_skip_spaces(*directive);
/* /*
* It should be enclosed in [ ]. * It should be enclosed in [ ].
* XXX: we don't check there is nothing else on the remainder of the *
* line, except a possible comment. * Strip off the comments. We should really strip the comments in
* generic code, not here. While we're at it, it would be better
* to pass the backend a series of tokens instead of a raw string,
* and actually process quoted strings for it, like of like argv
* is handled in C.
*/ */
if (*buf != '[') if (*buf != '[')
return D_none; return D_none;
q = strchr(buf, ']');
if (!q) q = buf;
return D_corrupt; while ((c = *q) != ']') {
switch (c) {
case '\0':
case ';':
return D_corrupt; /* No ] in directive */
case '\'':
case '\"':
case '`':
q = nasm_skip_string(q);
if (!*q++)
return D_corrupt;
break;
default:
q++;
break;
}
}
/* /*
* Strip off the comments. XXX: this doesn't account for quoted * Found the ] at the end of the directive. Make sure there isn't
* strings inside a directive. We should really strip the * anything else at the end of the line, except a possible
* comments in generic code, not here. While we're at it, it * comment.
* would be better to pass the backend a series of tokens instead
* of a raw string, and actually process quoted strings for it,
* like of like argv is handled in C.
*/ */
p = strchr(buf, ';'); eol = nasm_skip_spaces(q+1);
if (p) { if (*eol != '\0' && *eol != ';') {
if (p < q) /* ouch! somewhere inside */ nasm_warn(WARN_DIRECTIVE_GARBAGE_EOL,
return D_corrupt; "garbage found on line after directive");
*p = '\0';
} }
/* no brace, no trailing spaces */ /* no brace, no trailing spaces */
@@ -264,7 +282,7 @@ bool process_directives(char *directive)
switch (d) { switch (d) {
case D_none: case D_none:
return D_none; /* Not a directive */ return false;
case D_corrupt: case D_corrupt:
nasm_nonfatal("invalid directive line"); nasm_nonfatal("invalid directive line");
@@ -285,6 +303,12 @@ bool process_directives(char *directive)
default: default:
panic(); panic();
} }
} else if (d < D_pseudo_ops) {
nasm_nonfatal("internal error: unimplemented directive [%s]",
directive);
break;
} else {
goto unknown;
} }
break; break;
@@ -617,11 +641,10 @@ bool process_directives(char *directive)
break; break;
} }
/* A common error message */ /* A common error message */
if (bad_param) { if (bad_param) {
nasm_nonfatal("invalid parameter to [%s] directive", directive); nasm_nonfatal("invalid parameter to [%s] directive", directive);
} }
return d != D_none; return true;
} }

View File

@@ -17,6 +17,12 @@
;; In the future, this will be turned into a general list of keywords ;; In the future, this will be turned into a general list of keywords
;; to be parsed in special contexts. ;; to be parsed in special contexts.
;; ;;
;; #special tokens are used to separate different classes of tokens.
;; Make sure to add new tokens to the correct place. If a token is used
;; in both a directive and in pragmas, they should be in the directive
;; part of the list. Tokens used in pragmas *only* go at the end of the
;; list.
;;
; --- General configuration ; --- General configuration
#name directive #name directive
@@ -25,10 +31,15 @@
#header directiv.h #header directiv.h
; --- Special enum values ; --- Special enum values
; These must be first in the list.
#special none = 0 ; Must be zero #special none = 0 ; Must be zero
#special unknown #special unknown
#special corrupt #special corrupt
; --- True directives
; These tokens are accepted as directives by the global code or
; ignored if not implemented.
; --- Global directives ; --- Global directives
absolute absolute
bits bits
@@ -40,16 +51,29 @@ dollarhex
extern extern
float float
global global
static
list list
section
segment
warning
sectalign
pragma pragma
required required
sectalign
section
segment
static
warning
; --- Common output directives/pragmas
prefix
suffix
postfix
gprefix
gsuffix
gpostfix
lprefix
lsuffix
lpostfix
; --- Pseudo-op list, for the benefit of %isdirective ; --- Pseudo-op list, for the benefit of %isdirective
; Tokens put in this part will be rejected as either directives or
; pragmas
#special pseudo_ops #special pseudo_ops
db db
dw dw
@@ -71,6 +95,8 @@ incbin
equ equ
; --- Format-specific directives ; --- Format-specific directives
; Tokens put in this part of the list will be forwarded to the
; backend ofmt->directive() method.
#special ofmt #special ofmt
export ; outcoff, outobj export ; outcoff, outobj
group ; outobj group ; outobj
@@ -83,7 +109,8 @@ osabi ; outelf
safeseh ; outcoff safeseh ; outcoff
uppercase ; outieee, outobj uppercase ; outieee, outobj
; --- The following are tokens used in pragmas, not actual directives ; --- The following are tokens used in pragmas, not actual directives.
; They will not be accepted as directives.
#special pragma_tokens #special pragma_tokens
; --- Assembler pragmas ; --- Assembler pragmas
@@ -92,17 +119,6 @@ limit
; --- Listing pragmas ; --- Listing pragmas
options options
; --- Common output pragmas
prefix
suffix
postfix
gprefix
gsuffix
gpostfix
lprefix
lsuffix
lpostfix
; --- Backend-specific pragmas ; --- Backend-specific pragmas
subsections_via_symbols ; macho subsections_via_symbols ; macho
no_dead_strip ; macho no_dead_strip ; macho

View File

@@ -9,6 +9,11 @@ db-empty [on] no operand for data declaration
This is permitted, but often indicative of an error. This is permitted, but often indicative of an error.
See \k{db}. See \k{db}.
directive-garbage-eol [err] garbage after directive
Text was found after a directive. This is a warning so it can be
suppressed, because previous versions of NASM did not check for
this condition.
ea-absolute [on] absolute address cannot be RIP-relative ea-absolute [on] absolute address cannot be RIP-relative
Warns that an address that is inherently absolute cannot Warns that an address that is inherently absolute cannot
be generated with RIP-relative encoding using \c{REL}, be generated with RIP-relative encoding using \c{REL},