Bug Summary

File:parse.c
Location:line 518, column 40
Description:Array access (from variable 'i_defs') results in a null pointer dereference

Annotated Source Code

1/*
2
3Copyright (c) 1993, 1994, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27#include "def.h"
28
29static int deftype (char *line, struct filepointer *filep,
30 struct inclist *file_red, struct inclist *file,
31 int parse_it);
32static int zero_value(char *filename, char *exp, struct filepointer *filep,
33 struct inclist *file_red);
34static int merge2defines(struct inclist *file1, struct inclist *file2);
35
36static int
37gobble(struct filepointer *filep, struct inclist *file,
38 struct inclist *file_red)
39{
40 char *line;
41 int type;
42
43 while ((line = getnextline(filep))) {
44 switch(type = deftype(line, filep, file_red, file, FALSE0)) {
45 case IF0:
46 case IFFALSE17:
47 case IFGUESSFALSE20:
48 case IFDEF1:
49 case IFNDEF2:
50 type = gobble(filep, file, file_red);
51 while ((type == ELIF13) || (type == ELIFFALSE18) ||
52 (type == ELIFGUESSFALSE21))
53 type = gobble(filep, file, file_red);
54 if (type == ELSE3)
55 (void)gobble(filep, file, file_red);
56 break;
57 case ELSE3:
58 case ENDIF4:
59 debug(0,("%s, line %d: #%s\n",do { } while (0)
60 file->i_file, filep->f_line,do { } while (0)
61 directives[type]))do { } while (0);
62 return(type);
63 case DEFINE5:
64 case UNDEF6:
65 case INCLUDE7:
66 case INCLUDEDOT19:
67 case PRAGMA9:
68 case ERROR10:
69 case IDENT11:
70 case SCCS12:
71 case EJECT14:
72 case WARNING15:
73 case INCLUDENEXT16:
74 case INCLUDENEXTDOT22:
75 break;
76 case ELIF13:
77 case ELIFFALSE18:
78 case ELIFGUESSFALSE21:
79 return(type);
80 case -1:
81 warning("%s", file_red->i_file);
82 if (file_red != file)
83 warning1(" (reading %s)", file->i_file);
84 warning1(", line %ld: unknown directive == \"%s\"\n",
85 filep->f_line, line);
86 break;
87 }
88 }
89 return(-1);
90}
91
92/*
93 * Decide what type of # directive this line is.
94 */
95static int
96deftype (char *line, struct filepointer *filep,
97 struct inclist *file_red, struct inclist *file, int parse_it)
98{
99 register char *p;
100 char *directive, savechar, *q;
101 register int ret;
102
103 /*
104 * Parse the directive...
105 */
106 directive=line+1;
107 while (*directive == ' ' || *directive == '\t')
108 directive++;
109
110 p = directive;
111 while ((*p == '_') || (*p >= 'a' && *p <= 'z'))
112 p++;
113 savechar = *p;
114 *p = '\0';
115 ret = match(directive, directives);
116 *p = savechar;
117
118 /* If we don't recognize this compiler directive or we happen to just
119 * be gobbling up text while waiting for an #endif or #elif or #else
120 * in the case of an #elif we must check the zero_value and return an
121 * ELIF or an ELIFFALSE.
122 */
123
124 if (ret == ELIF13 && !parse_it)
125 {
126 while (*p == ' ' || *p == '\t')
127 p++;
128 /*
129 * parse an expression.
130 */
131 debug(0,("%s, line %d: #elif %s ",do { } while (0)
132 file->i_file, filep->f_line, p))do { } while (0);
133 ret = zero_value(file->i_file, p, filep, file_red);
134 if (ret != IF0)
135 {
136 debug(0,("false...\n"))do { } while (0);
137 if (ret == IFFALSE17)
138 return(ELIFFALSE18);
139 else
140 return(ELIFGUESSFALSE21);
141 }
142 else
143 {
144 debug(0,("true...\n"))do { } while (0);
145 return(ELIF13);
146 }
147 }
148
149 if (ret < 0 || ! parse_it)
150 return(ret);
151
152 /*
153 * now decide how to parse the directive, and do it.
154 */
155 while (*p == ' ' || *p == '\t')
156 p++;
157 q = p + strlen(p);
158 do {
159 q--;
160 } while (*q == ' ' || *q == '\t');
161 q[1] = '\0';
162 switch (ret) {
163 case IF0:
164 /*
165 * parse an expression.
166 */
167 ret = zero_value(file->i_file, p, filep, file_red);
168 debug(0,("%s, line %d: %s #if %s\n",do { } while (0)
169 file->i_file, filep->f_line, ret?"false":"true", p))do { } while (0);
170 break;
171 case IFDEF1:
172 case IFNDEF2:
173 debug(0,("%s, line %d: #%s %s\n",do { } while (0)
174 file->i_file, filep->f_line, directives[ret], p))do { } while (0);
175 case UNDEF6:
176 /*
177 * separate the name of a single symbol.
178 */
179 while (isalnum(*p) || *p == '_')
180 *line++ = *p++;
181 *line = '\0';
182 break;
183 case INCLUDE7:
184 case INCLUDENEXT16:
185 debug(2,("%s, line %d: #include%s %s\n",do { } while (0)
186 file->i_file, filep->f_line,do { } while (0)
187 (ret == INCLUDE) ? "" : "_next", p))do { } while (0);
188
189 /* Support ANSI macro substitution */
190 while (1) {
191 struct symtab **sym;
192
193 if (!*p || *p == '"' || *p == '<')
194 break;
195
196 sym = isdefined(p, file_red, NULL((void *)0));
197 if (!sym)
198 break;
199
200 p = (*sym)->s_value;
201 debug(3,("%s : #includes SYMBOL %s = %s\n",do { } while (0)
202 file->i_incstring,do { } while (0)
203 (*sym) -> s_name,do { } while (0)
204 (*sym) -> s_value))do { } while (0);
205 /* mark file as having included a 'soft include' */
206 file->i_flags |= INCLUDED_SYM(1<<5);
207 }
208
209 /*
210 * Separate the name of the include file.
211 */
212 while (*p && *p != '"' && *p != '<')
213 p++;
214 if (! *p)
215 return(-2);
216 if (*p++ == '"') {
217 if (ret == INCLUDE7)
218 ret = INCLUDEDOT19;
219 else
220 ret = INCLUDENEXTDOT22;
221 while (*p && *p != '"')
222 *line++ = *p++;
223 } else
224 while (*p && *p != '>')
225 *line++ = *p++;
226 *line = '\0';
227 break;
228 case DEFINE5:
229 /*
230 * copy the definition back to the beginning of the line.
231 */
232 memmove (line, p, strlen(p) + 1)__builtin___memmove_chk (line, p, strlen(p) + 1, __builtin_object_size
(line, 0))
;
233 break;
234 case ELSE3:
235 case ENDIF4:
236 case ELIF13:
237 case PRAGMA9:
238 case ERROR10:
239 case IDENT11:
240 case SCCS12:
241 case EJECT14:
242 case WARNING15:
243 debug(0,("%s, line %d: #%s\n",do { } while (0)
244 file->i_file, filep->f_line, directives[ret]))do { } while (0);
245 /*
246 * nothing to do.
247 */
248 break;
249 }
250 return(ret);
251}
252
253struct symtab **
254fdefined(const char *symbol, struct inclist *file, struct inclist **srcfile)
255{
256 struct inclist **ip;
257 struct symtab **val;
258 int i;
259 static int recurse_lvl = 0;
260
261 if (file->i_flags & DEFCHECKED(1<<0))
14
Taking false branch
262 return(NULL((void *)0));
263 debug(2,("Looking for %s in %s\n", symbol, file->i_file))do { } while (0);
264 file->i_flags |= DEFCHECKED(1<<0);
265 if ((val = slookup(symbol, file)))
15
Taking false branch
266 debug(1,("%s defined in %s as %s\n",do { } while (0)
267 symbol, file->i_file, (*val)->s_value))do { } while (0);
268 if (val == NULL((void *)0) && file->i_list)
16
Taking true branch
269 {
270 for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
17
Loop condition is true. Entering loop body
19
Loop condition is true. Entering loop body
21
Loop condition is true. Entering loop body
23
Loop condition is true. Entering loop body
271 if (file->i_merged[i]==FALSE0) {
18
Taking false branch
20
Taking false branch
22
Taking false branch
24
Taking true branch
272 val = fdefined(symbol, *ip, srcfile);
273 file->i_merged[i]=merge2defines(file,*ip);
25
Calling 'merge2defines'
274 if (val!=NULL((void *)0)) break;
275 }
276 }
277 else if (val != NULL((void *)0) && srcfile != NULL((void *)0)) *srcfile = file;
278 recurse_lvl--;
279 file->i_flags &= ~DEFCHECKED(1<<0);
280
281 return(val);
282}
283
284struct symtab **
285isdefined(const char *symbol, struct inclist *file, struct inclist **srcfile)
286{
287 struct symtab **val;
288
289 if ((val = slookup(symbol, &maininclist))) {
12
Taking false branch
290 debug(1,("%s defined on command line\n", symbol))do { } while (0);
291 if (srcfile != NULL((void *)0)) *srcfile = &maininclist;
292 return(val);
293 }
294 if ((val = fdefined(symbol, file, srcfile)))
13
Calling 'fdefined'
295 return(val);
296 debug(1,("%s not defined in %s\n", symbol, file->i_file))do { } while (0);
297 return(NULL((void *)0));
298}
299
300/*
301 * Return type based on if the #if expression evaluates to 0
302 */
303static int
304zero_value(char *filename,
305 char *exp,
306 struct filepointer *filep,
307 struct inclist *file_red)
308{
309 if (cppsetup(filename, exp, filep, file_red))
310 return(IFFALSE17);
311 else
312 return(IF0);
313}
314
315void
316define2(const char *name, const char *val, struct inclist *file)
317{
318 int first, last, below;
319 register struct symtab **sp = NULL((void *)0), **dest;
320 struct symtab *stab;
321
322 /* Make space if it's needed */
323 if (file->i_defs == NULL((void *)0))
324 {
325 file->i_defs = malloc(sizeof (struct symtab*) * SYMTABINC10);
326 file->i_ndefs = 0;
327 }
328 else if (!(file->i_ndefs % SYMTABINC10))
329 file->i_defs = realloc(file->i_defs,
330 sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC10));
331
332 if (file->i_defs == NULL((void *)0))
333 fatalerr("malloc()/realloc() failure in insert_defn()\n");
334
335 below = first = 0;
336 last = file->i_ndefs - 1;
337 while (last >= first)
338 {
339 /* Fast inline binary search */
340 register const char *s1;
341 register const char *s2;
342 register int middle = (first + last) / 2;
343
344 /* Fast inline strchr() */
345 s1 = name;
346 s2 = file->i_defs[middle]->s_name;
347 while (*s1++ == *s2++)
348 if (s2[-1] == '\0') break;
349
350 /* If exact match, set sp and break */
351 if (*--s1 == *--s2)
352 {
353 sp = file->i_defs + middle;
354 break;
355 }
356
357 /* If name > i_defs[middle] ... */
358 if (*s1 > *s2)
359 {
360 below = first;
361 first = middle + 1;
362 }
363 /* else ... */
364 else
365 {
366 below = last = middle - 1;
367 }
368 }
369
370 /* Search is done. If we found an exact match to the symbol name,
371 just replace its s_value */
372 if (sp != NULL((void *)0))
373 {
374 debug(1,("redefining %s from %s to %s in file %s\n",do { } while (0)
375 name, (*sp)->s_value, val, file->i_file))do { } while (0);
376 free((*sp)->s_value);
377 (*sp)->s_value = strdup(val);
378 return;
379 }
380
381 sp = file->i_defs + file->i_ndefs++;
382 dest = file->i_defs + below + 1;
383 while (sp > dest)
384 {
385 *sp = sp[-1];
386 sp--;
387 }
388 stab = malloc(sizeof (struct symtab));
389 if (stab == NULL((void *)0))
390 fatalerr("malloc()/realloc() failure in insert_defn()\n");
391
392 debug(1,("defining %s to %s in file %s\n", name, val, file->i_file))do { } while (0);
393 stab->s_name = strdup(name);
394 stab->s_value = strdup(val);
395 *sp = stab;
396}
397
398void
399define(char *def, struct inclist *file)
400{
401 char *val;
402
403 /* Separate symbol name and its value */
404 val = def;
405 while (isalnum(*val) || *val == '_')
406 val++;
407 if (*val)
408 *val++ = '\0';
409 while (*val == ' ' || *val == '\t')
410 val++;
411
412 if (!*val)
413 define2(def, "1", file);
414 else
415 define2(def, val, file);
416}
417
418struct symtab **
419slookup(const char *symbol, struct inclist *file)
420{
421 register int first = 0;
422 register int last;
423
424 if (file == NULL((void *)0))
425 return NULL((void *)0);
426
427 last = file->i_ndefs - 1;
428
429 while (last >= first)
430 {
431 /* Fast inline binary search */
432 register const char *s1;
433 register const char *s2;
434 register int middle = (first + last) / 2;
435
436 /* Fast inline strchr() */
437 s1 = symbol;
438 s2 = file->i_defs[middle]->s_name;
439 while (*s1++ == *s2++)
440 if (s2[-1] == '\0') break;
441
442 /* If exact match, we're done */
443 if (*--s1 == *--s2)
444 {
445 return file->i_defs + middle;
446 }
447
448 /* If symbol > i_defs[middle] ... */
449 if (*s1 > *s2)
450 {
451 first = middle + 1;
452 }
453 /* else ... */
454 else
455 {
456 last = middle - 1;
457 }
458 }
459 return(NULL((void *)0));
460}
461
462static int
463merge2defines(struct inclist *file1, struct inclist *file2)
464{
465 int i;
466
467 if ((file1==NULL((void *)0)) || (file2==NULL((void *)0)) ||
26
Assuming 'file2' is not equal to null
27
Taking false branch
468 !(file2->i_flags & FINISHED(1<<4)))
469 return 0;
470
471 for (i=0; i < file2->i_listlen; i++)
28
Loop condition is false. Execution continues on line 476
472 if (file2->i_merged[i]==FALSE0)
473 return 0;
474
475 {
476 int first1 = 0;
477 int last1 = file1->i_ndefs - 1;
478
479 int first2 = 0;
480 int last2 = file2->i_ndefs - 1;
481
482 int first=0;
483 struct symtab** i_defs = NULL((void *)0);
29
'i_defs' initialized to a null pointer value
484 int deflen=file1->i_ndefs+file2->i_ndefs;
485
486 debug(2,("merging %s into %s\n",do { } while (0)
487 file2->i_file, file1->i_file))do { } while (0);
488
489 if (deflen>0)
30
Assuming 'deflen' is <= 0
31
Taking false branch
490 {
491 /* make sure deflen % SYMTABINC == 0 is still true */
492 deflen += (SYMTABINC10 - deflen % SYMTABINC10) % SYMTABINC10;
493 i_defs = malloc(deflen*sizeof(struct symtab*));
494 if (i_defs==NULL((void *)0)) return 0;
495 }
496
497 while ((last1 >= first1) && (last2 >= first2))
498 {
499 const char *s1 = file1->i_defs[first1]->s_name;
500 const char *s2 = file2->i_defs[first2]->s_name;
501
502 if (strcmp(s1,s2) < 0)
503 i_defs[first++]=file1->i_defs[first1++];
504 else if (strcmp(s1,s2) > 0)
505 i_defs[first++]=file2->i_defs[first2++];
506 else /* equal */
507 {
508 i_defs[first++]=file2->i_defs[first2++];
509 first1++;
510 }
511 }
512 while (last1 >= first1)
32
Loop condition is false. Execution continues on line 516
513 {
514 i_defs[first++]=file1->i_defs[first1++];
515 }
516 while (last2 >= first2)
33
Assuming 'last2' is >= 'first2'
34
Loop condition is true. Entering loop body
517 {
518 i_defs[first++]=file2->i_defs[first2++];
35
Array access (from variable 'i_defs') results in a null pointer dereference
519 }
520
521 if (file1->i_defs) free(file1->i_defs);
522 file1->i_defs=i_defs;
523 file1->i_ndefs=first;
524
525 return 1;
526 }
527}
528
529void
530undefine(const char *symbol, struct inclist *file)
531{
532 register struct symtab **ptr;
533 struct inclist *srcfile;
534 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL((void *)0))
11
Calling 'isdefined'
535 {
536 srcfile->i_ndefs--;
537 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
538 *ptr = ptr[1];
539 }
540}
541
542int
543find_includes(struct filepointer *filep, struct inclist *file,
544 struct inclist *file_red, int recursion, boolean failOK)
545{
546 struct inclist *inclistp;
547 const char **includedirsp;
548 register char *line;
549 register int type;
550 boolean recfailOK;
551
552 while ((line = getnextline(filep))) {
1
Loop condition is true. Entering loop body
3
Loop condition is true. Entering loop body
5
Loop condition is true. Entering loop body
7
Loop condition is true. Entering loop body
553 switch(type = deftype(line, filep, file_red, file, TRUE1)) {
2
'Default' branch taken. Execution continues on line 552
4
'Default' branch taken. Execution continues on line 552
6
'Default' branch taken. Execution continues on line 552
8
Control jumps to 'case 6:' at line 624
554 case IF0:
555 doif:
556 type = find_includes(filep, file,
557 file_red, recursion+1, failOK);
558 while ((type == ELIF13) || (type == ELIFFALSE18) ||
559 (type == ELIFGUESSFALSE21))
560 type = gobble(filep, file, file_red);
561 if (type == ELSE3)
562 gobble(filep, file, file_red);
563 break;
564 case IFFALSE17:
565 case IFGUESSFALSE20:
566 doiffalse:
567 if (type == IFGUESSFALSE20 || type == ELIFGUESSFALSE21)
568 recfailOK = TRUE1;
569 else
570 recfailOK = failOK;
571 type = gobble(filep, file, file_red);
572 if (type == ELSE3)
573 find_includes(filep, file,
574 file_red, recursion+1, recfailOK);
575 else
576 if (type == ELIF13)
577 goto doif;
578 else
579 if ((type == ELIFFALSE18) || (type == ELIFGUESSFALSE21))
580 goto doiffalse;
581 break;
582 case IFDEF1:
583 case IFNDEF2:
584 if ((type == IFDEF1 && isdefined(line, file_red, NULL((void *)0)))
585 || (type == IFNDEF2 && !isdefined(line, file_red, NULL((void *)0)))) {
586 debug(1,(type == IFNDEF ?do { } while (0)
587 "line %d: %s !def'd in %s via %s%s\n" : "",do { } while (0)
588 filep->f_line, line,do { } while (0)
589 file->i_file, file_red->i_file, ": doit"))do { } while (0);
590 type = find_includes(filep, file,
591 file_red, recursion+1, failOK);
592 while (type == ELIF13 || type == ELIFFALSE18 || type == ELIFGUESSFALSE21)
593 type = gobble(filep, file, file_red);
594 if (type == ELSE3)
595 gobble(filep, file, file_red);
596 }
597 else {
598 debug(1,(type == IFDEF ?do { } while (0)
599 "line %d: %s !def'd in %s via %s%s\n" : "",do { } while (0)
600 filep->f_line, line,do { } while (0)
601 file->i_file, file_red->i_file, ": gobble"))do { } while (0);
602 type = gobble(filep, file, file_red);
603 if (type == ELSE3)
604 find_includes(filep, file,
605 file_red, recursion+1, failOK);
606 else if (type == ELIF13)
607 goto doif;
608 else if (type == ELIFFALSE18 || type == ELIFGUESSFALSE21)
609 goto doiffalse;
610 }
611 break;
612 case ELSE3:
613 case ELIFFALSE18:
614 case ELIFGUESSFALSE21:
615 case ELIF13:
616 if (!recursion)
617 gobble(filep, file, file_red);
618 case ENDIF4:
619 if (recursion)
620 return(type);
621 case DEFINE5:
622 define(line, file);
623 break;
624 case UNDEF6:
625 if (!*line) {
9
Taking false branch
626 warning("%s", file_red->i_file);
627 if (file_red != file)
628 warning1(" (reading %s)", file->i_file);
629 warning1(", line %ld: incomplete undef == \"%s\"\n",
630 filep->f_line, line);
631 break;
632 }
633 undefine(line, file_red);
10
Calling 'undefine'
634 break;
635 case INCLUDE7:
636 case INCLUDEDOT19:
637 case INCLUDENEXT16:
638 case INCLUDENEXTDOT22:
639 inclistp = inclistnext;
640 includedirsp = includedirsnext;
641 debug(2,("%s, reading %s, includes %s\n",do { } while (0)
642 file_red->i_file, file->i_file, line))do { } while (0);
643 add_include(filep, file, file_red, line, type, failOK);
644 inclistnext = inclistp;
645 includedirsnext = includedirsp;
646 break;
647 case ERROR10:
648 case WARNING15:
649 warning("%s", file_red->i_file);
650 if (file_red != file)
651 warning1(" (reading %s)", file->i_file);
652 warning1(", line %ld: %s\n",
653 filep->f_line, line);
654 break;
655
656 case PRAGMA9:
657 case IDENT11:
658 case SCCS12:
659 case EJECT14:
660 break;
661 case -1:
662 warning("%s", file_red->i_file);
663 if (file_red != file)
664 warning1(" (reading %s)", file->i_file);
665 warning1(", line %ld: unknown directive == \"%s\"\n",
666 filep->f_line, line);
667 break;
668 case -2:
669 warning("%s", file_red->i_file);
670 if (file_red != file)
671 warning1(" (reading %s)", file->i_file);
672 warning1(", line %ld: incomplete include == \"%s\"\n",
673 filep->f_line, line);
674 break;
675 }
676 }
677 file->i_flags |= FINISHED(1<<4);
678 debug(2,("finished with %s\n", file->i_file))do { } while (0);
679 return(-1);
680}