Skip to content

Commit c0aec69

Browse files
author
H. Peter Anvin (Intel)
committed
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>
1 parent 5a6b276 commit c0aec69

File tree

3 files changed

+80
-36
lines changed

3 files changed

+80
-36
lines changed

asm/directiv.c

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "listing.h"
2323
#include "labels.h"
2424
#include "iflag.h"
25+
#include "quote.h"
2526

2627
struct cpunames {
2728
const char *name;
@@ -178,34 +179,51 @@ static int get_bits(const char *value)
178179

179180
static enum directive parse_directive_line(char **directive, char **value)
180181
{
181-
char *p, *q, *buf;
182+
char *p, *q, *eol, *buf;
183+
char c;
182184

183185
buf = nasm_skip_spaces(*directive);
184186

185187
/*
186188
* It should be enclosed in [ ].
187-
* XXX: we don't check there is nothing else on the remainder of the
188-
* line, except a possible comment.
189+
*
190+
* Strip off the comments. We should really strip the comments in
191+
* generic code, not here. While we're at it, it would be better
192+
* to pass the backend a series of tokens instead of a raw string,
193+
* and actually process quoted strings for it, like of like argv
194+
* is handled in C.
189195
*/
190196
if (*buf != '[')
191197
return D_none;
192-
q = strchr(buf, ']');
193-
if (!q)
194-
return D_corrupt;
198+
199+
q = buf;
200+
while ((c = *q) != ']') {
201+
switch (c) {
202+
case '\0':
203+
case ';':
204+
return D_corrupt; /* No ] in directive */
205+
case '\'':
206+
case '\"':
207+
case '`':
208+
q = nasm_skip_string(q);
209+
if (!*q++)
210+
return D_corrupt;
211+
break;
212+
default:
213+
q++;
214+
break;
215+
}
216+
}
195217

196218
/*
197-
* Strip off the comments. XXX: this doesn't account for quoted
198-
* strings inside a directive. We should really strip the
199-
* comments in generic code, not here. While we're at it, it
200-
* would be better to pass the backend a series of tokens instead
201-
* of a raw string, and actually process quoted strings for it,
202-
* like of like argv is handled in C.
219+
* Found the ] at the end of the directive. Make sure there isn't
220+
* anything else at the end of the line, except a possible
221+
* comment.
203222
*/
204-
p = strchr(buf, ';');
205-
if (p) {
206-
if (p < q) /* ouch! somewhere inside */
207-
return D_corrupt;
208-
*p = '\0';
223+
eol = nasm_skip_spaces(q+1);
224+
if (*eol != '\0' && *eol != ';') {
225+
nasm_warn(WARN_DIRECTIVE_GARBAGE_EOL,
226+
"garbage found on line after directive");
209227
}
210228

211229
/* no brace, no trailing spaces */
@@ -264,7 +282,7 @@ bool process_directives(char *directive)
264282

265283
switch (d) {
266284
case D_none:
267-
return D_none; /* Not a directive */
285+
return false;
268286

269287
case D_corrupt:
270288
nasm_nonfatal("invalid directive line");
@@ -285,6 +303,12 @@ bool process_directives(char *directive)
285303
default:
286304
panic();
287305
}
306+
} else if (d < D_pseudo_ops) {
307+
nasm_nonfatal("internal error: unimplemented directive [%s]",
308+
directive);
309+
break;
310+
} else {
311+
goto unknown;
288312
}
289313
break;
290314

@@ -617,11 +641,10 @@ bool process_directives(char *directive)
617641
break;
618642
}
619643

620-
621644
/* A common error message */
622645
if (bad_param) {
623646
nasm_nonfatal("invalid parameter to [%s] directive", directive);
624647
}
625648

626-
return d != D_none;
649+
return true;
627650
}

asm/directiv.dat

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
;; In the future, this will be turned into a general list of keywords
1818
;; to be parsed in special contexts.
1919
;;
20+
;; #special tokens are used to separate different classes of tokens.
21+
;; Make sure to add new tokens to the correct place. If a token is used
22+
;; in both a directive and in pragmas, they should be in the directive
23+
;; part of the list. Tokens used in pragmas *only* go at the end of the
24+
;; list.
25+
;;
2026

2127
; --- General configuration
2228
#name directive
@@ -25,10 +31,15 @@
2531
#header directiv.h
2632

2733
; --- Special enum values
34+
; These must be first in the list.
2835
#special none = 0 ; Must be zero
2936
#special unknown
3037
#special corrupt
3138

39+
; --- True directives
40+
; These tokens are accepted as directives by the global code or
41+
; ignored if not implemented.
42+
3243
; --- Global directives
3344
absolute
3445
bits
@@ -40,16 +51,29 @@ dollarhex
4051
extern
4152
float
4253
global
43-
static
4454
list
55+
pragma
56+
required
57+
sectalign
4558
section
4659
segment
60+
static
4761
warning
48-
sectalign
49-
pragma
50-
required
62+
63+
; --- Common output directives/pragmas
64+
prefix
65+
suffix
66+
postfix
67+
gprefix
68+
gsuffix
69+
gpostfix
70+
lprefix
71+
lsuffix
72+
lpostfix
5173

5274
; --- Pseudo-op list, for the benefit of %isdirective
75+
; Tokens put in this part will be rejected as either directives or
76+
; pragmas
5377
#special pseudo_ops
5478
db
5579
dw
@@ -71,6 +95,8 @@ incbin
7195
equ
7296

7397
; --- Format-specific directives
98+
; Tokens put in this part of the list will be forwarded to the
99+
; backend ofmt->directive() method.
74100
#special ofmt
75101
export ; outcoff, outobj
76102
group ; outobj
@@ -83,7 +109,8 @@ osabi ; outelf
83109
safeseh ; outcoff
84110
uppercase ; outieee, outobj
85111

86-
; --- The following are tokens used in pragmas, not actual directives
112+
; --- The following are tokens used in pragmas, not actual directives.
113+
; They will not be accepted as directives.
87114
#special pragma_tokens
88115

89116
; --- Assembler pragmas
@@ -92,17 +119,6 @@ limit
92119
; --- Listing pragmas
93120
options
94121

95-
; --- Common output pragmas
96-
prefix
97-
suffix
98-
postfix
99-
gprefix
100-
gsuffix
101-
gpostfix
102-
lprefix
103-
lsuffix
104-
lpostfix
105-
106122
; --- Backend-specific pragmas
107123
subsections_via_symbols ; macho
108124
no_dead_strip ; macho

asm/warnings.dat

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ db-empty [on] no operand for data declaration
99
This is permitted, but often indicative of an error.
1010
See \k{db}.
1111

12+
directive-garbage-eol [err] garbage after directive
13+
Text was found after a directive. This is a warning so it can be
14+
suppressed, because previous versions of NASM did not check for
15+
this condition.
16+
1217
ea-absolute [on] absolute address cannot be RIP-relative
1318
Warns that an address that is inherently absolute cannot
1419
be generated with RIP-relative encoding using \c{REL},

0 commit comments

Comments
 (0)