Mercurial > hg > index.cgi
annotate lwcc/cpp.c @ 577:e49d24f4a9a5
Correct bug in the object file output code leading to stack corruption
It turns out leaving a pointer to a stack allocated temporary in a
persistent data structure is not conducive to correct program operation.
Undo the export check setup in the object file output sequence so a
pointer to stack allocated memory is not left hanging when the function
returns. This seems to correct at least one mysterious crash bug, and
possibly others.
Thanks to Boisy Pitre for reporting the crash bug that led to this
discovery, as well as a previous crash bug that likely has the same
root cause.
Additional thanks to Ciaran Anscomb whose debugger wielding wizardry
revealed the exact location of this particular bit of unbrilliance.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sat, 03 Aug 2024 14:30:06 -0600 |
parents | 670ea8f90212 |
children |
rev | line source |
---|---|
295 | 1 /* |
2 lwcc/cpp.c | |
3 | |
4 Copyright © 2013 William Astle | |
5 | |
6 This file is part of LWTOOLS. | |
7 | |
8 LWTOOLS is free software: you can redistribute it and/or modify it under the | |
9 terms of the GNU General Public License as published by the Free Software | |
10 Foundation, either version 3 of the License, or (at your option) any later | |
11 version. | |
12 | |
13 This program is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
16 more details. | |
17 | |
18 You should have received a copy of the GNU General Public License along with | |
19 this program. If not, see <http://www.gnu.org/licenses/>. | |
20 */ | |
21 | |
22 #include <stdarg.h> | |
23 #include <stdio.h> | |
24 #include <stdlib.h> | |
25 #include <string.h> | |
26 | |
27 #include <lw_alloc.h> | |
28 #include <lw_string.h> | |
306
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
29 #include <lw_stringlist.h> |
308
670ea8f90212
Converted preproc logic to library and moved some utility stuff to lwlib
William Astle <lost@l-w.ca>
parents:
306
diff
changeset
|
30 #include <lw_strpool.h> |
295 | 31 #include "cpp.h" |
308
670ea8f90212
Converted preproc logic to library and moved some utility stuff to lwlib
William Astle <lost@l-w.ca>
parents:
306
diff
changeset
|
32 |
295 | 33 |
34 struct token *preproc_lex_next_token(struct preproc_info *); | |
35 | |
36 struct preproc_info *preproc_init(const char *fn) | |
37 { | |
38 FILE *fp; | |
39 struct preproc_info *pp; | |
40 | |
41 if (!fn || (fn[0] == '-' && fn[1] == '0')) | |
42 { | |
43 fp = stdin; | |
44 } | |
45 else | |
46 { | |
47 fp = fopen(fn, "rb"); | |
48 } | |
49 if (!fp) | |
50 return NULL; | |
51 | |
52 pp = lw_alloc(sizeof(struct preproc_info)); | |
53 memset(pp, 0, sizeof(struct preproc_info)); | |
308
670ea8f90212
Converted preproc logic to library and moved some utility stuff to lwlib
William Astle <lost@l-w.ca>
parents:
306
diff
changeset
|
54 pp -> strpool = lw_strpool_create(); |
670ea8f90212
Converted preproc logic to library and moved some utility stuff to lwlib
William Astle <lost@l-w.ca>
parents:
306
diff
changeset
|
55 pp -> fn = lw_strpool_strdup(pp -> strpool, fn); |
295 | 56 pp -> fp = fp; |
57 pp -> ra = CPP_NOUNG; | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
58 pp -> unget = CPP_NOUNG; |
296 | 59 pp -> ppeolseen = 1; |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
60 pp -> lineno = 1; |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
61 pp -> n = NULL; |
306
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
62 pp -> quotelist = lw_stringlist_create(); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
63 pp -> inclist = lw_stringlist_create(); |
295 | 64 return pp; |
65 } | |
66 | |
306
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
67 void preproc_add_include(struct preproc_info *pp, char *dir, int sys) |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
68 { |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
69 if (sys) |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
70 lw_stringlist_addstring(pp -> inclist, dir); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
71 else |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
72 lw_stringlist_addstring(pp -> quotelist, dir); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
73 } |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
74 |
295 | 75 struct token *preproc_next_token(struct preproc_info *pp) |
76 { | |
77 struct token *t; | |
78 | |
296 | 79 if (pp -> curtok) |
80 token_free(pp -> curtok); | |
81 | |
82 /* | |
83 If there is a list of tokens to process, move it to the "unget" queue | |
84 with an EOF marker at the end of it. | |
85 */ | |
86 if (pp -> sourcelist) | |
87 { | |
88 for (t = pp -> sourcelist; t -> next; t = t -> next) | |
89 /* do nothing */ ; | |
90 t -> next = token_create(TOK_EOF, NULL, -1, -1, ""); | |
91 t -> next -> next = pp -> tokqueue; | |
92 pp -> tokqueue = pp -> sourcelist; | |
93 pp -> sourcelist = NULL; | |
94 } | |
95 again: | |
295 | 96 if (pp -> tokqueue) |
97 { | |
98 t = pp -> tokqueue; | |
99 pp -> tokqueue = t -> next; | |
100 if (pp -> tokqueue) | |
101 pp -> tokqueue -> prev = NULL; | |
102 t -> next = NULL; | |
103 t -> prev = NULL; | |
296 | 104 pp -> curtok = t; |
105 goto ret; | |
295 | 106 } |
296 | 107 pp -> curtok = preproc_lex_next_token(pp); |
108 t = pp -> curtok; | |
109 ret: | |
110 if (t -> ttype == TOK_ENDEXPAND) | |
111 { | |
112 struct expand_e *e; | |
113 e = pp -> expand_list; | |
114 pp -> expand_list = e -> next; | |
115 lw_free(e); | |
116 goto again; | |
117 } | |
118 return t; | |
119 } | |
120 | |
121 void preproc_unget_token(struct preproc_info *pp, struct token *t) | |
122 { | |
123 t -> next = pp -> tokqueue; | |
124 pp -> tokqueue = t; | |
125 if (pp -> curtok == t) | |
126 pp -> curtok = NULL; | |
295 | 127 } |
128 | |
129 void preproc_finish(struct preproc_info *pp) | |
130 { | |
131 fclose(pp -> fp); | |
306
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
132 lw_stringlist_destroy(pp -> inclist); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
133 lw_stringlist_destroy(pp -> quotelist); |
296 | 134 if (pp -> curtok) |
135 token_free(pp -> curtok); | |
136 while (pp -> tokqueue) | |
137 { | |
138 preproc_next_token(pp); | |
139 token_free(pp -> curtok); | |
140 } | |
308
670ea8f90212
Converted preproc logic to library and moved some utility stuff to lwlib
William Astle <lost@l-w.ca>
parents:
306
diff
changeset
|
141 lw_strpool_free(pp -> strpool); |
295 | 142 lw_free(pp); |
143 } | |
144 | |
145 void preproc_register_error_callback(struct preproc_info *pp, void (*cb)(const char *)) | |
146 { | |
147 pp -> errorcb = cb; | |
148 } | |
149 | |
150 void preproc_register_warning_callback(struct preproc_info *pp, void (*cb)(const char *)) | |
151 { | |
152 pp -> warningcb = cb; | |
153 } | |
154 | |
155 static void preproc_throw_error_default(const char *m) | |
156 { | |
157 fprintf(stderr, "ERROR: %s\n", m); | |
158 } | |
159 | |
160 static void preproc_throw_warning_default(const char *m) | |
161 { | |
162 fprintf(stderr, "WARNING: %s\n", m); | |
163 } | |
164 | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
165 static void preproc_throw_message(struct preproc_info *pp, void (*cb)(const char *), const char *m, va_list args) |
295 | 166 { |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
167 int s, s2; |
295 | 168 char *b; |
169 | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
170 s2 = snprintf(NULL, 0, "(%s:%d:%d) ", pp -> fn, pp -> lineno, pp -> column); |
295 | 171 s = vsnprintf(NULL, 0, m, args); |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
172 b = lw_alloc(s + s2 + 1); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
173 snprintf(b, s2 + 1, "(%s:%d:%d) ", pp -> fn, pp -> lineno, pp -> column); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
174 vsnprintf(b + s2, s + 1, m, args); |
295 | 175 (*cb)(b); |
176 lw_free(b); | |
177 } | |
178 | |
179 void preproc_throw_error(struct preproc_info *pp, const char *m, ...) | |
180 { | |
181 va_list args; | |
182 va_start(args, m); | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
183 preproc_throw_message(pp, pp -> errorcb ? pp -> errorcb : preproc_throw_error_default, m, args); |
295 | 184 va_end(args); |
185 exit(1); | |
186 } | |
187 | |
188 void preproc_throw_warning(struct preproc_info *pp, const char *m, ...) | |
189 { | |
190 va_list args; | |
191 va_start(args, m); | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
192 preproc_throw_message(pp, pp -> warningcb ? pp -> warningcb : preproc_throw_warning_default, m, args); |
295 | 193 va_end(args); |
194 } |