Bug Summary

File:parse.c
Location:line 521, column 25
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",
60 file->i_file, filep->f_line,
61 directives[type]));
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 ",
132 file->i_file, filep->f_line, p));
133 ret = zero_value(file->i_file, p, filep, file_red);
134 if (ret != IF0)
135 {
136 debug(0,("false...\n"));
137 if (ret == IFFALSE17)
138 return(ELIFFALSE18);
139 else
140 return(ELIFGUESSFALSE21);
141 }
142 else
143 {
144 debug(0,("true...\n"));
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",
169 file->i_file, filep->f_line, ret?"false":"true", p));
170 break;
171 case IFDEF1:
172 case IFNDEF2:
173 debug(0,("%s, line %d: #%s %s\n",
174 file->i_file, filep->f_line, directives[ret], p));
175 case UNDEF6:
176 /*
177 * separate the name of a single symbol.
178 */
179 while (isalnum(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int)
_ISalnum)
|| *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",
186 file->i_file, filep->f_line,
187 (ret == INCLUDE) ? "" : "_next", p));
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",
202 file->i_incstring,
203 (*sym) -> s_name,
204 (*sym) -> s_value));
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 strcpy (line, p);
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",
244 file->i_file, filep->f_line, directives[ret]));
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))
262 return(NULL((void*)0));
263 debug(2,("Looking for %s in %s\n", symbol, file->i_file));
264 file->i_flags |= DEFCHECKED(1<<0);
265 if ((val = slookup(symbol, file)))
266 debug(1,("%s defined in %s as %s\n",
267 symbol, file->i_file, (*val)->s_value));
268 if (val == NULL((void*)0) && file->i_list)
269 {
270 for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
271 if (file->i_merged[i]==FALSE0) {
272 val = fdefined(symbol, *ip, srcfile);
273 file->i_merged[i]=merge2defines(file,*ip);
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))) {
290 debug(1,("%s defined on command line\n", symbol));
291 if (srcfile != NULL((void*)0)) *srcfile = &maininclist;
292 return(val);
293 }
294 if ((val = fdefined(symbol, file, srcfile)))
295 return(val);
296 debug(1,("%s not defined in %s\n", symbol, file->i_file));
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 = (struct symtab **)
326 malloc(sizeof (struct symtab*) * SYMTABINC10);
327 file->i_ndefs = 0;
328 }
329 else if (!(file->i_ndefs % SYMTABINC10))
330 file->i_defs = (struct symtab **)
331 realloc(file->i_defs,
332 sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC10));
333
334 if (file->i_defs == NULL((void*)0))
335 fatalerr("malloc()/realloc() failure in insert_defn()\n");
336
337 below = first = 0;
338 last = file->i_ndefs - 1;
339 while (last >= first)
340 {
341 /* Fast inline binary search */
342 register const char *s1;
343 register const char *s2;
344 register int middle = (first + last) / 2;
345
346 /* Fast inline strchr() */
347 s1 = name;
348 s2 = file->i_defs[middle]->s_name;
349 while (*s1++ == *s2++)
350 if (s2[-1] == '\0') break;
351
352 /* If exact match, set sp and break */
353 if (*--s1 == *--s2)
354 {
355 sp = file->i_defs + middle;
356 break;
357 }
358
359 /* If name > i_defs[middle] ... */
360 if (*s1 > *s2)
361 {
362 below = first;
363 first = middle + 1;
364 }
365 /* else ... */
366 else
367 {
368 below = last = middle - 1;
369 }
370 }
371
372 /* Search is done. If we found an exact match to the symbol name,
373 just replace its s_value */
374 if (sp != NULL((void*)0))
375 {
376 debug(1,("redefining %s from %s to %s in file %s\n",
377 name, (*sp)->s_value, val, file->i_file));
378 free((*sp)->s_value);
379 (*sp)->s_value = strdup(val);
380 return;
381 }
382
383 sp = file->i_defs + file->i_ndefs++;
384 dest = file->i_defs + below + 1;
385 while (sp > dest)
386 {
387 *sp = sp[-1];
388 sp--;
389 }
390 stab = (struct symtab *) malloc(sizeof (struct symtab));
391 if (stab == NULL((void*)0))
392 fatalerr("malloc()/realloc() failure in insert_defn()\n");
393
394 debug(1,("defining %s to %s in file %s\n", name, val, file->i_file));
395 stab->s_name = strdup(name);
396 stab->s_value = strdup(val);
397 *sp = stab;
398}
399
400void
401define(char *def, struct inclist *file)
402{
403 char *val;
404
405 /* Separate symbol name and its value */
406 val = def;
407 while (isalnum(*val)((*__ctype_b_loc ())[(int) ((*val))] & (unsigned short int
) _ISalnum)
|| *val == '_')
408 val++;
409 if (*val)
410 *val++ = '\0';
411 while (*val == ' ' || *val == '\t')
412 val++;
413
414 if (!*val)
415 define2(def, "1", file);
416 else
417 define2(def, val, file);
418}
419
420struct symtab **
421slookup(const char *symbol, struct inclist *file)
422{
423 register int first = 0;
424 register int last;
425
426 if (file == NULL((void*)0))
427 return NULL((void*)0);
428
429 last = file->i_ndefs - 1;
430
431 while (last >= first)
432 {
433 /* Fast inline binary search */
434 register const char *s1;
435 register const char *s2;
436 register int middle = (first + last) / 2;
437
438 /* Fast inline strchr() */
439 s1 = symbol;
440 s2 = file->i_defs[middle]->s_name;
441 while (*s1++ == *s2++)
442 if (s2[-1] == '\0') break;
443
444 /* If exact match, we're done */
445 if (*--s1 == *--s2)
446 {
447 return file->i_defs + middle;
448 }
449
450 /* If symbol > i_defs[middle] ... */
451 if (*s1 > *s2)
452 {
453 first = middle + 1;
454 }
455 /* else ... */
456 else
457 {
458 last = middle - 1;
459 }
460 }
461 return(NULL((void*)0));
462}
463
464static int
465merge2defines(struct inclist *file1, struct inclist *file2)
466{
467 int i;
468
469 if ((file1==NULL((void*)0)) || (file2==NULL((void*)0)) ||
1
Assuming 'file1' is not equal to null
2
Assuming 'file2' is not equal to null
3
Taking false branch
470 !(file2->i_flags & FINISHED(1<<4)))
471 return 0;
472
473 for (i=0; i < file2->i_listlen; i++)
4
Loop condition is false. Execution continues on line 478
474 if (file2->i_merged[i]==FALSE0)
475 return 0;
476
477 {
478 int first1 = 0;
479 int last1 = file1->i_ndefs - 1;
480
481 int first2 = 0;
482 int last2 = file2->i_ndefs - 1;
483
484 int first=0;
485 struct symtab** i_defs = NULL((void*)0);
486 int deflen=file1->i_ndefs+file2->i_ndefs;
487
488 debug(2,("merging %s into %s\n",
489 file2->i_file, file1->i_file));
490
491 if (deflen>0)
5
Assuming 'deflen' is <= 0
6
Taking false branch
492 {
493 /* make sure deflen % SYMTABINC == 0 is still true */
494 deflen += (SYMTABINC10 - deflen % SYMTABINC10) % SYMTABINC10;
495 i_defs=(struct symtab**)
496 malloc(deflen*sizeof(struct symtab*));
497 if (i_defs==NULL((void*)0)) return 0;
498 }
499
500 while ((last1 >= first1) && (last2 >= first2))
7
Assuming 'last1' is < 'first1'
8
Loop condition is false. Execution continues on line 515
501 {
502 char *s1=file1->i_defs[first1]->s_name;
503 char *s2=file2->i_defs[first2]->s_name;
504
505 if (strcmp(s1,s2) < 0)
506 i_defs[first++]=file1->i_defs[first1++];
507 else if (strcmp(s1,s2) > 0)
508 i_defs[first++]=file2->i_defs[first2++];
509 else /* equal */
510 {
511 i_defs[first++]=file2->i_defs[first2++];
512 first1++;
513 }
514 }
515 while (last1 >= first1)
9
Loop condition is false. Execution continues on line 519
516 {
517 i_defs[first++]=file1->i_defs[first1++];
518 }
519 while (last2 >= first2)
10
Assuming 'last2' is >= 'first2'
11
Loop condition is true. Entering loop body
520 {
521 i_defs[first++]=file2->i_defs[first2++];
12
Array access (from variable 'i_defs') results in a null pointer dereference
522 }
523
524 if (file1->i_defs) free(file1->i_defs);
525 file1->i_defs=i_defs;
526 file1->i_ndefs=first;
527
528 return 1;
529 }
530}
531
532void
533undefine(const char *symbol, struct inclist *file)
534{
535 register struct symtab **ptr;
536 struct inclist *srcfile;
537 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL((void*)0))
538 {
539 srcfile->i_ndefs--;
540 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
541 *ptr = ptr[1];
542 }
543}
544
545int
546find_includes(struct filepointer *filep, struct inclist *file,
547 struct inclist *file_red, int recursion, boolean failOK)
548{
549 struct inclist *inclistp;
550 const char **includedirsp;
551 register char *line;
552 register int type;
553 boolean recfailOK;
554
555 while ((line = getnextline(filep))) {
556 switch(type = deftype(line, filep, file_red, file, TRUE1)) {
557 case IF0:
558 doif:
559 type = find_includes(filep, file,
560 file_red, recursion+1, failOK);
561 while ((type == ELIF13) || (type == ELIFFALSE18) ||
562 (type == ELIFGUESSFALSE21))
563 type = gobble(filep, file, file_red);
564 if (type == ELSE3)
565 gobble(filep, file, file_red);
566 break;
567 case IFFALSE17:
568 case IFGUESSFALSE20:
569 doiffalse:
570 if (type == IFGUESSFALSE20 || type == ELIFGUESSFALSE21)
571 recfailOK = TRUE1;
572 else
573 recfailOK = failOK;
574 type = gobble(filep, file, file_red);
575 if (type == ELSE3)
576 find_includes(filep, file,
577 file_red, recursion+1, recfailOK);
578 else
579 if (type == ELIF13)
580 goto doif;
581 else
582 if ((type == ELIFFALSE18) || (type == ELIFGUESSFALSE21))
583 goto doiffalse;
584 break;
585 case IFDEF1:
586 case IFNDEF2:
587 if ((type == IFDEF1 && isdefined(line, file_red, NULL((void*)0)))
588 || (type == IFNDEF2 && !isdefined(line, file_red, NULL((void*)0)))) {
589 debug(1,(type == IFNDEF ?
590 "line %d: %s !def'd in %s via %s%s\n" : "",
591 filep->f_line, line,
592 file->i_file, file_red->i_file, ": doit"));
593 type = find_includes(filep, file,
594 file_red, recursion+1, failOK);
595 while (type == ELIF13 || type == ELIFFALSE18 || type == ELIFGUESSFALSE21)
596 type = gobble(filep, file, file_red);
597 if (type == ELSE3)
598 gobble(filep, file, file_red);
599 }
600 else {
601 debug(1,(type == IFDEF ?
602 "line %d: %s !def'd in %s via %s%s\n" : "",
603 filep->f_line, line,
604 file->i_file, file_red->i_file, ": gobble"));
605 type = gobble(filep, file, file_red);
606 if (type == ELSE3)
607 find_includes(filep, file,
608 file_red, recursion+1, failOK);
609 else if (type == ELIF13)
610 goto doif;
611 else if (type == ELIFFALSE18 || type == ELIFGUESSFALSE21)
612 goto doiffalse;
613 }
614 break;
615 case ELSE3:
616 case ELIFFALSE18:
617 case ELIFGUESSFALSE21:
618 case ELIF13:
619 if (!recursion)
620 gobble(filep, file, file_red);
621 case ENDIF4:
622 if (recursion)
623 return(type);
624 case DEFINE5:
625 define(line, file);
626 break;
627 case UNDEF6:
628 if (!*line) {
629 warning("%s", file_red->i_file);
630 if (file_red != file)
631 warning1(" (reading %s)", file->i_file);
632 warning1(", line %ld: incomplete undef == \"%s\"\n",
633 filep->f_line, line);
634 break;
635 }
636 undefine(line, file_red);
637 break;
638 case INCLUDE7:
639 case INCLUDEDOT19:
640 case INCLUDENEXT16:
641 case INCLUDENEXTDOT22:
642 inclistp = inclistnext;
643 includedirsp = includedirsnext;
644 debug(2,("%s, reading %s, includes %s\n",
645 file_red->i_file, file->i_file, line));
646 add_include(filep, file, file_red, line, type, failOK);
647 inclistnext = inclistp;
648 includedirsnext = includedirsp;
649 break;
650 case ERROR10:
651 case WARNING15:
652 warning("%s", file_red->i_file);
653 if (file_red != file)
654 warning1(" (reading %s)", file->i_file);
655 warning1(", line %ld: %s\n",
656 filep->f_line, line);
657 break;
658
659 case PRAGMA9:
660 case IDENT11:
661 case SCCS12:
662 case EJECT14:
663 break;
664 case -1:
665 warning("%s", file_red->i_file);
666 if (file_red != file)
667 warning1(" (reading %s)", file->i_file);
668 warning1(", line %ld: unknown directive == \"%s\"\n",
669 filep->f_line, line);
670 break;
671 case -2:
672 warning("%s", file_red->i_file);
673 if (file_red != file)
674 warning1(" (reading %s)", file->i_file);
675 warning1(", line %ld: incomplete include == \"%s\"\n",
676 filep->f_line, line);
677 break;
678 }
679 }
680 file->i_flags |= FINISHED(1<<4);
681 debug(2,("finished with %s\n", file->i_file));
682 return(-1);
683}