clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name _macro.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -std=gnu89 -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c /home/maarten/src/libreoffice/core/soltools/cpp/_macro.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | #include <stdio.h> |
21 | #include <stdlib.h> |
22 | #include <string.h> |
23 | #if defined(__IBMC__) || defined(__EMX__) || defined(_MSC_VER) |
24 | # ifndef PATH_MAX |
25 | # define PATH_MAX _MAX_PATH |
26 | # endif |
27 | #endif |
28 | #include <limits.h> |
29 | |
30 | #include "cpp.h" |
31 | |
32 | #define NCONCAT 16384 |
33 | |
34 | |
35 | |
36 | |
37 | void |
38 | dodefine(Tokenrow * trp) |
39 | { |
40 | Token *tp; |
41 | Nlist *np; |
42 | Source *s; |
43 | Tokenrow *def, *args; |
44 | static uchar location[(PATH_MAX + 8) * NINC], *cp; |
45 | |
46 | tp = trp->tp + 1; |
47 | if (tp >= trp->lp || tp->type != NAME) |
48 | { |
49 | error(ERROR, "#defined token is not a name"); |
50 | return; |
51 | } |
52 | np = lookup(tp, 1); |
53 | if (np->flag & ISUNCHANGE) |
54 | { |
55 | error(ERROR, "#defined token %t can't be redefined", tp); |
56 | return; |
57 | } |
58 | |
59 | tp += 1; |
60 | args = NULL; |
61 | if (tp < trp->lp && tp->type == LP && tp->wslen == 0) |
62 | { |
63 | tp += 1; |
64 | args = new(Tokenrow); |
65 | maketokenrow(2, args); |
66 | if (tp->type != RP) |
67 | { |
68 | |
69 | size_t narg = 0; |
70 | int err = 0; |
71 | |
72 | for (;;) |
73 | { |
74 | Token *atp; |
75 | |
76 | if (tp->type != NAME) |
77 | { |
78 | err++; |
79 | break; |
80 | } |
81 | if (narg >= args->max) |
82 | growtokenrow(args); |
83 | for (atp = args->bp; atp < args->lp; atp++) |
84 | if (atp->len == tp->len |
85 | && strncmp((char *) atp->t, (char *) tp->t, tp->len) == 0) |
86 | error(ERROR, "Duplicate macro argument"); |
87 | *args->lp++ = *tp; |
88 | narg++; |
89 | tp += 1; |
90 | if (tp->type == RP) |
91 | break; |
92 | if (tp->type != COMMA) |
93 | { |
94 | err++; |
95 | break; |
96 | } |
97 | tp += 1; |
98 | } |
99 | if (err) |
100 | { |
101 | error(ERROR, "Syntax error in macro parameters"); |
102 | return; |
103 | } |
104 | } |
105 | tp += 1; |
106 | } |
107 | trp->tp = tp; |
108 | if (((trp->lp) - 1)->type == NL) |
109 | trp->lp -= 1; |
110 | def = normtokenrow(trp); |
111 | if (np->flag & ISDEFINED) |
112 | { |
113 | if (comparetokens(def, np->vp) |
114 | || (np->ap == NULL) != (args == NULL) |
115 | || (np->ap && comparetokens(args, np->ap))) |
116 | { |
117 | if ( np->loc ) |
118 | error(ERROR, |
119 | "Macro redefinition of %t (already defined at %s)", |
120 | trp->bp + 2, np->loc); |
121 | else |
122 | error(ERROR, |
123 | "Macro redefinition of %t (already defined at %s)", |
124 | trp->bp + 2, "commandline" ); |
125 | } |
126 | } |
127 | if (args) |
128 | { |
129 | Tokenrow *tap; |
130 | |
131 | tap = normtokenrow(args); |
132 | dofree(args->bp); |
133 | dofree(args); |
134 | args = tap; |
135 | } |
136 | np->ap = args; |
137 | np->vp = def; |
138 | np->flag |= ISDEFINED; |
139 | |
140 | |
141 | for (cp = location, s = cursource; s; s = s->next) |
142 | if (*s->filename) |
143 | { |
144 | if (cp != location) |
145 | *cp++ = ' '; |
146 | sprintf((char *)cp, "%s:%d", s->filename, s->line); |
147 | cp += strlen((char *)cp); |
148 | } |
149 | |
150 | np->loc = newstring(location, strlen((char *)location), 0); |
151 | |
152 | if (Mflag) |
153 | { |
154 | if (np->ap) |
155 | error(INFO, "Macro definition of %s(%r) [%r]", np->name, np->ap, np->vp); |
156 | else |
157 | error(INFO, "Macro definition of %s [%r]", np->name, np->vp); |
158 | } |
159 | } |
160 | |
161 | |
162 | |
163 | |
164 | void |
165 | doadefine(Tokenrow * trp, int type) |
166 | { |
167 | Nlist *np; |
168 | static uchar onestr[2] = "1"; |
169 | static Token onetoken[1] = {{NUMBER, 0, 1, onestr, 0}}; |
170 | static Tokenrow onetr = {onetoken, onetoken, onetoken + 1, 1}; |
171 | |
172 | trp->tp = trp->bp; |
173 | if (type == 'U') |
174 | { |
175 | if (trp->lp - trp->tp != 2 || trp->tp->type != NAME) |
176 | goto syntax; |
177 | if ((np = lookup(trp->tp, 0)) == NULL) |
178 | return; |
179 | np->flag &= ~ISDEFINED; |
180 | return; |
181 | } |
182 | |
183 | if (type == 'A') |
184 | { |
185 | if (trp->tp >= trp->lp || trp->tp->type != NAME) |
186 | goto syntax; |
187 | trp->tp->type = ARCHITECTURE; |
188 | np = lookup(trp->tp, 1); |
189 | np->flag |= ISARCHITECTURE; |
190 | trp->tp += 1; |
191 | if (trp->tp >= trp->lp || trp->tp->type == END) |
192 | { |
193 | np->vp = &onetr; |
194 | return; |
195 | } |
196 | else |
197 | error(FATAL, "Illegal -A argument %r", trp); |
198 | } |
199 | |
200 | if (trp->tp >= trp->lp || trp->tp->type != NAME) |
201 | goto syntax; |
202 | np = lookup(trp->tp, 1); |
203 | np->flag |= ISDEFINED; |
204 | trp->tp += 1; |
205 | if (trp->tp >= trp->lp || trp->tp->type == END) |
206 | { |
207 | np->vp = &onetr; |
208 | return; |
209 | } |
210 | if (trp->tp->type != ASGN) |
211 | goto syntax; |
212 | trp->tp += 1; |
213 | if ((trp->lp - 1)->type == END) |
214 | trp->lp -= 1; |
215 | np->vp = normtokenrow(trp); |
216 | return; |
217 | syntax: |
218 | error(FATAL, "Illegal -D or -U argument %r", trp); |
219 | } |
220 | |
221 | |
222 | |
223 | |
224 | |
225 | |
226 | |
227 | void |
228 | expandrow(Tokenrow * trp, char *flag) |
229 | { |
230 | Token * tp; |
231 | Nlist * np; |
232 | |
233 | MacroValidatorList validators; |
234 | mvl_init(&validators); |
235 | |
236 | tokenrow_zeroTokenIdentifiers(trp); |
237 | |
238 | if (flag) |
| |
| |
239 | setsource(flag, -1, -1, "", 0); |
240 | for (tp = trp->tp; tp < trp->lp;) |
| 3 | | Assuming 'tp' is < field 'lp' | |
|
| 4 | | Loop condition is true. Entering loop body | |
|
241 | { |
242 | mvl_check(&validators, tp); |
243 | |
244 | if (tp->type != NAME |
| 5 | | Assuming field 'type' is equal to NAME | |
|
| |
245 | || quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0) == 0 |
| 6 | | Assuming field 'len' is <= 1 | |
|
| |
| 8 | | Assuming the condition is false | |
|
246 | || (np = lookup(tp, 0)) == NULL |
| 9 | | Value assigned to 'cursource' | |
|
| 10 | | Assuming the condition is false | |
|
247 | || (np->flag & (ISDEFINED | ISMAC)) == 0 |
| 11 | | Assuming the condition is false | |
|
248 | || (np->flag & ISACTIVE) != 0) |
| 12 | | Assuming the condition is false | |
|
249 | { |
250 | tp++; |
251 | continue; |
252 | } |
253 | trp->tp = tp; |
254 | if (np->val == KDEFINED) |
| 14 | | Assuming field 'val' is not equal to KDEFINED | |
|
| |
255 | { |
256 | tp->type = DEFINED; |
257 | if ((tp + 1) < trp->lp && (tp + 1)->type == NAME) |
258 | (tp + 1)->type = NAME1; |
259 | else |
260 | if ((tp + 3) < trp->lp && (tp + 1)->type == LP |
261 | && (tp + 2)->type == NAME && (tp + 3)->type == RP) |
262 | (tp + 2)->type = NAME1; |
263 | else |
264 | error(ERROR, "Incorrect syntax for `defined'"); |
265 | tp++; |
266 | continue; |
267 | } |
268 | else |
269 | if (np->val == KMACHINE) |
| 16 | | Assuming field 'val' is not equal to KMACHINE | |
|
| |
270 | { |
271 | if (((tp - 1) >= trp->bp) && ((tp - 1)->type == SHARP)) |
272 | { |
273 | tp->type = ARCHITECTURE; |
274 | if ((tp + 1) < trp->lp && (tp + 1)->type == NAME) |
275 | (tp + 1)->type = NAME2; |
276 | else |
277 | if ((tp + 3) < trp->lp && (tp + 1)->type == LP |
278 | && (tp + 2)->type == NAME && (tp + 3)->type == RP) |
279 | (tp + 2)->type = NAME2; |
280 | else |
281 | error(ERROR, "Incorrect syntax for `#machine'"); |
282 | } |
283 | tp++; |
284 | continue; |
285 | } |
286 | |
287 | if (np->flag & ISMAC) |
| 18 | | Assuming the condition is true | |
|
| |
288 | builtin(trp, np->val); |
| |
289 | else |
290 | { |
291 | |
292 | expand(trp, np, &validators); |
293 | } |
294 | tp = trp->tp; |
295 | } |
296 | if (flag) |
297 | unsetsource(); |
298 | |
299 | mvl_destruct(&validators); |
300 | } |
301 | |
302 | |
303 | |
304 | |
305 | |
306 | |
307 | |
308 | |
309 | |
310 | void |
311 | expand(Tokenrow * trp, Nlist * np, MacroValidatorList * pValidators) |
312 | { |
313 | Tokenrow ntr; |
314 | int ntokc, narg; |
315 | Tokenrow *atr[NARG + 1]; |
316 | |
317 | if (Mflag == 2) |
318 | { |
319 | if (np->ap) |
320 | error(INFO, "Macro expansion of %t with %s(%r)", trp->tp, np->name, np->ap); |
321 | else |
322 | error(INFO, "Macro expansion of %t with %s", trp->tp, np->name); |
323 | } |
324 | |
325 | copytokenrow(&ntr, np->vp); |
326 | if (np->ap == NULL) |
327 | ntokc = 1; |
328 | else |
329 | { |
330 | int i; |
331 | |
332 | ntokc = gatherargs(trp, atr, &narg); |
333 | if (narg < 0) |
334 | { |
335 | trp->tp++; |
336 | return; |
337 | } |
338 | if (narg != rowlen(np->ap)) |
339 | { |
340 | error(ERROR, "Disagreement in number of macro arguments"); |
341 | trp->tp += ntokc; |
342 | return; |
343 | } |
344 | |
345 | |
346 | |
347 | |
348 | |
349 | |
350 | for (i = 1; i < ntokc; i++) |
351 | { |
352 | mvl_check(pValidators,trp->tp+i); |
353 | } |
354 | |
355 | substargs(np, &ntr, atr); |
356 | for (i = 0; i < narg; i++) |
357 | { |
358 | dofree(atr[i]->bp); |
359 | dofree(atr[i]); |
360 | } |
361 | } |
362 | |
363 | doconcat(&ntr); |
364 | ntr.tp = ntr.bp; |
365 | makespace(&ntr, trp->tp); |
366 | |
367 | tokenrow_zeroTokenIdentifiers(&ntr); |
368 | insertrow(trp, ntokc, &ntr); |
369 | |
370 | |
371 | |
372 | np->flag |= ISACTIVE; |
373 | if (trp->tp != trp->lp) |
374 | { |
375 | mvl_add(pValidators,np,trp->tp); |
376 | } |
377 | else |
378 | { |
379 | mvl_add(pValidators,np,NULL); |
380 | } |
381 | |
382 | |
383 | trp->tp -= ntr.lp - ntr.bp; |
384 | |
385 | dofree(ntr.bp); |
386 | |
387 | return; |
388 | } |
389 | |
390 | |
391 | |
392 | |
393 | |
394 | |
395 | int |
396 | gatherargs(Tokenrow * trp, Tokenrow ** atr, int *narg) |
397 | { |
398 | int parens = 1; |
399 | int ntok = 0; |
400 | Token *bp, *lp; |
401 | Tokenrow ttr; |
402 | int ntokp; |
403 | int needspace; |
404 | |
405 | *narg = -1; |
406 | |
407 | |
408 | for (;;) |
409 | { |
410 | trp->tp++; |
411 | ntok++; |
412 | if (trp->tp >= trp->lp) |
413 | { |
414 | |
415 | gettokens(trp, 0); |
416 | if ((trp->lp - 1)->type == END) |
417 | { |
418 | trp->lp -= 1; |
419 | trp->tp -= ntok; |
420 | return ntok; |
421 | } |
422 | } |
423 | if (trp->tp->type == LP) |
424 | break; |
425 | if (trp->tp->type != NL) |
426 | return ntok; |
427 | } |
428 | *narg = 0; |
429 | ntok++; |
430 | ntokp = ntok; |
431 | trp->tp++; |
432 | |
433 | needspace = 0; |
434 | while (parens > 0) |
435 | { |
436 | if (trp->tp >= trp->lp) |
437 | { |
438 | |
439 | gettokens(trp, 0); |
440 | } |
441 | if (needspace) |
442 | { |
443 | needspace = 0; |
444 | |
445 | } |
446 | if (trp->tp->type == END) |
447 | { |
448 | trp->lp -= 1; |
449 | trp->tp -= ntok; |
450 | error(ERROR, "EOF in macro arglist"); |
451 | return ntok; |
452 | } |
453 | if (trp->tp->type == NL) |
454 | { |
455 | trp->tp += 1; |
456 | adjustrow(trp, -1); |
457 | trp->tp -= 1; |
458 | |
459 | needspace = 1; |
460 | continue; |
461 | } |
462 | if (trp->tp->type == LP) |
463 | parens++; |
464 | else |
465 | if (trp->tp->type == RP) |
466 | parens--; |
467 | trp->tp++; |
468 | ntok++; |
469 | } |
470 | trp->tp -= ntok; |
471 | |
472 | lp = bp = trp->tp + ntokp; |
473 | for (; parens >= 0; lp++) |
474 | { |
475 | if (lp->type == LP) |
476 | { |
477 | parens++; |
478 | continue; |
479 | } |
480 | if (lp->type == RP) |
481 | parens--; |
482 | if (lp->type == DSHARP) |
483 | lp->type = DSHARP1; |
484 | if ((lp->type == COMMA && parens == 0) || |
485 | ( parens < 0 && ((lp - 1)->type != LP))) |
486 | { |
487 | if (*narg >= NARG - 1) |
488 | error(FATAL, "Sorry, too many macro arguments"); |
489 | ttr.bp = ttr.tp = bp; |
490 | ttr.lp = lp; |
491 | atr[(*narg)++] = normtokenrow(&ttr); |
492 | bp = lp + 1; |
493 | } |
494 | } |
495 | return ntok; |
496 | } |
497 | |
498 | |
499 | |
500 | |
501 | |
502 | void |
503 | substargs(Nlist * np, Tokenrow * rtr, Tokenrow ** atr) |
504 | { |
505 | Tokenrow tatr; |
506 | Token *tp; |
507 | int ntok, argno; |
508 | |
509 | for (rtr->tp = rtr->bp; rtr->tp < rtr->lp;) |
510 | { |
511 | if (rtr->tp->type == SHARP) |
512 | { |
513 | tp = rtr->tp; |
514 | rtr->tp += 1; |
515 | if ((argno = lookuparg(np, rtr->tp)) < 0) |
516 | { |
517 | error(ERROR, "# not followed by macro parameter"); |
518 | continue; |
519 | } |
520 | ntok = 1 + (int)(rtr->tp - tp); |
521 | rtr->tp = tp; |
522 | insertrow(rtr, ntok, stringify(atr[argno])); |
523 | continue; |
524 | } |
525 | if (rtr->tp->type == NAME |
526 | && (argno = lookuparg(np, rtr->tp)) >= 0) |
527 | { |
528 | if (((rtr->tp + 1) < rtr->lp && (rtr->tp + 1)->type == DSHARP) |
529 | || (rtr->tp != rtr->bp && (rtr->tp - 1)->type == DSHARP)) |
530 | { |
531 | copytokenrow(&tatr, atr[argno]); |
532 | makespace(&tatr, rtr->tp); |
533 | insertrow(rtr, 1, &tatr); |
534 | dofree(tatr.bp); |
535 | } |
536 | else |
537 | { |
538 | copytokenrow(&tatr, atr[argno]); |
539 | makespace(&tatr, rtr->tp); |
540 | expandrow(&tatr, "<macro>"); |
541 | insertrow(rtr, 1, &tatr); |
542 | dofree(tatr.bp); |
543 | } |
544 | continue; |
545 | } |
546 | rtr->tp++; |
547 | } |
548 | } |
549 | |
550 | |
551 | |
552 | |
553 | void |
554 | doconcat(Tokenrow * trp) |
555 | { |
556 | Token *ltp, *ntp; |
557 | Tokenrow ntr; |
558 | size_t len; |
559 | |
560 | for (trp->tp = trp->bp; trp->tp < trp->lp; trp->tp++) |
561 | { |
562 | if (trp->tp->type == DSHARP1) |
563 | trp->tp->type = DSHARP; |
564 | else |
565 | if (trp->tp->type == DSHARP) |
566 | { |
567 | int i; |
568 | char tt[NCONCAT]; |
569 | |
570 | ltp = trp->tp - 1; |
571 | ntp = trp->tp + 1; |
572 | |
573 | if (ltp < trp->bp || ntp >= trp->lp) |
574 | { |
575 | error(ERROR, "## occurs at border of replacement"); |
576 | continue; |
577 | } |
578 | |
579 | ntp = ltp; |
580 | i = 1; |
581 | len = 0; |
582 | |
583 | do |
584 | { |
585 | if (len + ntp->len + ntp->wslen > sizeof(tt)) |
586 | { |
587 | error(ERROR, "## string concatenation buffer overrun"); |
588 | break; |
589 | } |
590 | |
591 | if (ntp != trp->tp + 1) |
592 | { |
593 | strncpy((char *) tt + len, (char *) ntp->t - ntp->wslen, |
594 | ntp->len + ntp->wslen); |
595 | len += ntp->len + ntp->wslen; |
596 | } |
597 | else |
598 | { |
599 | |
600 | strncpy((char *) tt + len, (char *) ntp->t, ntp->len); |
601 | len += ntp->len; |
602 | } |
603 | |
604 | ntp = trp->tp + i; |
605 | i++; |
606 | } |
607 | while (ntp < trp->lp); |
608 | |
609 | tt[len] = '\0'; |
610 | setsource("<##>", -1, -1, tt, 0); |
611 | maketokenrow(3, &ntr); |
612 | |
613 | gettokens(&ntr, 1); |
614 | unsetsource(); |
615 | if (ntr.bp->type == UNCLASS) |
616 | error(WARNING, "Bad token %r produced by ##", &ntr); |
617 | while ((ntr.lp-1)->len == 0 && ntr.lp != ntr.bp) |
618 | ntr.lp--; |
619 | |
620 | doconcat(&ntr); |
621 | trp->tp = ltp; |
622 | makespace(&ntr, ltp); |
623 | insertrow(trp, (int)(ntp - ltp), &ntr); |
624 | dofree(ntr.bp); |
625 | trp->tp--; |
626 | } |
627 | } |
628 | } |
629 | |
630 | |
631 | |
632 | |
633 | |
634 | |
635 | int |
636 | lookuparg(Nlist * mac, Token const * tp) |
637 | { |
638 | Token *ap; |
639 | |
640 | if (tp->type != NAME || mac->ap == NULL) |
641 | return -1; |
642 | for (ap = mac->ap->bp; ap < mac->ap->lp; ap++) |
643 | { |
644 | if (ap->len == tp->len && strncmp((char *) ap->t, (char *) tp->t, ap->len) == 0) |
645 | return (int)(ap - mac->ap->bp); |
646 | } |
647 | return -1; |
648 | } |
649 | |
650 | |
651 | |
652 | |
653 | #define STRLEN 512 |
654 | Tokenrow * |
655 | stringify(Tokenrow * vp) |
656 | { |
657 | static Token t = {STRING, 0, 0, NULL, 0}; |
658 | static Tokenrow tr = {&t, &t, &t + 1, 1}; |
659 | Token *tp; |
660 | uchar s[STRLEN]; |
661 | uchar *sp = s, *cp; |
662 | int i, instring; |
663 | |
664 | *sp++ = '"'; |
665 | for (tp = vp->bp; tp < vp->lp; tp++) |
666 | { |
667 | instring = tp->type == STRING || tp->type == CCON; |
668 | if (sp + 2 * tp->len + tp->wslen >= &s[STRLEN - 10]) |
669 | { |
670 | error(ERROR, "Stringified macro arg is too long"); |
671 | break; |
672 | } |
673 | |
674 | |
675 | if ( tp->wslen > 0 ) |
676 | *sp++ = ' '; |
677 | |
678 | |
679 | for (i = 0, cp = tp->t; (unsigned int)i < tp->len; i++) |
680 | { |
681 | if (instring && (*cp == '"' || *cp == '\\')) |
682 | *sp++ = '\\'; |
683 | *sp++ = *cp++; |
684 | } |
685 | } |
686 | *sp++ = '"'; |
687 | *sp = '\0'; |
688 | sp = s; |
689 | t.len = strlen((char *) sp); |
690 | t.t = newstring(sp, t.len, 0); |
691 | return &tr; |
692 | } |
693 | |
694 | |
695 | |
696 | |
697 | void |
698 | builtin(Tokenrow * trp, int biname) |
699 | { |
700 | char *op; |
701 | Token *tp; |
702 | Source *s; |
703 | |
704 | tp = trp->tp; |
705 | trp->tp++; |
706 | |
707 | s = cursource; |
708 | while (s && s->fd == -1) |
| |
709 | s = s->next; |
710 | if (s == NULL) |
| |
711 | s = cursource; |
| 23 | | Null pointer value stored to 's' | |
|
712 | |
713 | tp->type = STRING; |
714 | if (tp->wslen) |
| 24 | | Assuming field 'wslen' is 0 | |
|
| |
715 | { |
716 | *outptr++ = ' '; |
717 | tp->wslen = 1; |
718 | } |
719 | op = outptr; |
720 | *op++ = '"'; |
721 | switch (biname) |
| 26 | | Control jumps to 'case KLINENO:' at line 724 | |
|
722 | { |
723 | |
724 | case KLINENO: |
725 | tp->type = NUMBER; |
726 | op = outnum(op - 1, s->line); |
| 27 | | Access to field 'line' results in a dereference of a null pointer (loaded from variable 's') |
|
727 | break; |
728 | |
729 | case KFILE: |
730 | { |
731 | char *src = s->filename; |
732 | |
733 | while ((*op++ = *src++) != 0) |
734 | if (src[-1] == '\\') |
735 | *op++ = '\\'; |
736 | op--; |
737 | break; |
738 | } |
739 | |
740 | case KDATE: |
741 | strncpy(op, curtime + 4, 7); |
742 | strncpy(op + 7, curtime + 20, 4); |
743 | op += 11; |
744 | break; |
745 | |
746 | case KTIME: |
747 | strncpy(op, curtime + 11, 8); |
748 | op += 8; |
749 | break; |
750 | |
751 | default: |
752 | error(ERROR, "cpp botch: unknown internal macro"); |
753 | return; |
754 | } |
755 | if (tp->type == STRING) |
756 | *op++ = '"'; |
757 | tp->t = (uchar *) outptr; |
758 | tp->len = op - outptr; |
759 | outptr = op; |
760 | } |
761 | |
762 | |