Bug Summary

File:home/maarten/src/libreoffice/core/soltools/mkdepend/parse.c
Warning:line 347, column 36
Array access (via field 's_pairs') results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name parse.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 NO_X11 -D XP_PC -D HW_THREADS -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/mkdepend/parse.c
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */
3/*
4
5Copyright (c) 1993, 1994 X Consortium
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in
15all copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of the X Consortium shall not be
25used in advertising or otherwise to promote the sale, use or other dealings
26in this Software without prior written authorization from the X Consortium.
27
28*/
29
30#include <ctype.h>
31
32#include "def.h"
33static char *hash_lookup( char *symbol, struct symhash *symbols );
34static int gobble( struct filepointer *filep, struct inclist *file,
35 struct inclist *file_red, struct symhash *symbols );
36static int deftype ( char *line, struct filepointer *filep, struct inclist *file,
37 int parse_it, struct symhash *symbols);
38static int zero_value(char const *exp, struct symhash *symbols);
39
40extern struct symhash *maininclist;
41
42int find_includes(struct filepointer *filep, struct inclist *file, struct inclist *file_red, int recursion, boolean failOK, struct IncludesCollection* incCollection, struct symhash *symbols)
43{
44 char *line;
45 int type;
46
47 while ((line = get_line(filep))) {
1
Loop condition is true. Entering loop body
48 type = deftype(line, filep, file, TRUE1, symbols);
2
Calling 'deftype'
13
Returning from 'deftype'
49 switch(type) {
14
Control jumps to 'case 16:' at line 66
50 case IF0:
51 doif:
52 type = find_includes(filep, file,
53 file_red, recursion+1, failOK, incCollection, symbols);
54 while ((type == ELIF13) || (type == ELIFFALSE16) ||
55 (type == ELIFGUESSFALSE19))
56 type = gobble(filep, file, file_red, symbols);
57 break;
58 case IFFALSE15:
59 doiffalse:
60 type = gobble(filep, file, file_red, symbols);
61 if (type == ELIF13)
62 goto doif;
63 else if ((type == ELIFFALSE16) || (type == ELIFGUESSFALSE19))
64 goto doiffalse;
65 break;
66 case ELIFFALSE16:
67 case ELIFGUESSFALSE19:
68 case ELIF13:
69 if (!recursion)
15
Assuming 'recursion' is 0
16
Taking true branch
70 gobble(filep, file, file_red, symbols);
71 if (recursion
16.1
'recursion' is 0
)
17
Taking false branch
72 return type;
73 define(line, &symbols);
18
Calling 'define'
74 break;
75 case ERROR10:
76 warning("%s: %d: %s\n", file_red->i_file,
77 filep->f_line, line);
78 break;
79
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 %d: unknown directive == \"%s\"\n",
85 filep->f_line, line);
86 break;
87 case -2:
88 warning("%s", file_red->i_file);
89 if (file_red != file)
90 warning1(" (reading %s)", file->i_file);
91 warning1(", line %d: incomplete include == \"%s\"\n",
92 filep->f_line, line);
93 break;
94 }
95 }
96 // coverity[leaked_storage] - on purpose
97 return -1;
98}
99
100int gobble(struct filepointer *filep,
101 struct inclist *file,
102 struct inclist *file_red,
103 struct symhash *symbols)
104{
105 char *line;
106 int type;
107
108 while ((line = get_line(filep))) {
109 type = deftype(line, filep, file, FALSE0, symbols);
110 switch(type) {
111 case IF0:
112 case IFFALSE15:
113 type = gobble(filep, file, file_red, symbols);
114 while ((type == ELIF13) || (type == ELIFFALSE16) ||
115 (type == ELIFGUESSFALSE19))
116 type = gobble(filep, file, file_red, symbols);
117 break;
118 case ERROR10:
119 break;
120 case ELIF13:
121 case ELIFFALSE16:
122 case ELIFGUESSFALSE19:
123 return type;
124 case -1:
125 warning("%s, line %d: unknown directive == \"%s\"\n",
126 file_red->i_file, filep->f_line, line);
127 break;
128 }
129 }
130 return -1;
131}
132
133/*
134 * Decide what type of # directive this line is.
135 */
136int deftype (char *line, struct filepointer *filep, struct inclist * file,
137 int parse_it, struct symhash *symbols)
138{
139 char *p;
140 char *directive, savechar;
141 int ret;
142 (void)file; // used in DEBUG mode
143 (void)filep;
144 /*
145 * Parse the directive...
146 */
147 directive=line+1;
148 while (*directive == ' ' || *directive == '\t')
3
Assuming the condition is false
4
Assuming the condition is false
5
Loop condition is false. Execution continues on line 151
149 directive++;
150
151 p = directive;
152 while (*p >= 'a' && *p <= 'z')
6
Assuming the condition is false
153 p++;
154 savechar = *p;
155 *p = '\0';
156 ret = match(directive, directives);
157 *p = savechar;
158
159 /* If we don't recognize this compiler directive or we happen to just
160 * be gobbling up text while waiting for an #endif or #elif or #else
161 * in the case of an #elif we must check the zero_value and return an
162 * ELIF or an ELIFFALSE.
163 */
164
165 if (ret == ELIF13 && !parse_it)
7
Assuming 'ret' is not equal to ELIF
166 {
167 while (*p == ' ' || *p == '\t')
168 p++;
169 /*
170 * parse an expression.
171 */
172 debug(0,("%s, line %d: #elif %s ",
173 file->i_file, filep->f_line, p));
174 ret = zero_value(p, symbols);
175 if (ret != IF0)
176 {
177 debug(0,("false...\n"));
178 if (ret == IFFALSE15)
179 return ELIFFALSE16;
180 else
181 return ELIFGUESSFALSE19;
182 }
183 else
184 {
185 debug(0,("true...\n"));
186 return ELIF13;
187 }
188 }
189
190 if (ret < 0 || ! parse_it
8.1
'parse_it' is 1
)
8
Assuming 'ret' is >= 0
9
Taking false branch
191 return ret;
192
193 /*
194 * now decide how to parse the directive, and do it.
195 */
196 while (*p == ' ' || *p == '\t')
10
Loop condition is false. Execution continues on line 198
197 p++;
198 switch (ret) {
11
'Default' branch taken. Execution continues on line 216
199 case IF0:
200 /*
201 * parse an expression.
202 */
203 ret = zero_value(p, symbols);
204 debug(0,("%s, line %d: %s #if %s\n",
205 file->i_file, filep->f_line, ret?"false":"true", p));
206 break;
207 case ELIF13:
208 case ERROR10:
209 debug(0,("%s, line %d: #%s\n",
210 file->i_file, filep->f_line, directives[ret]));
211 /*
212 * nothing to do.
213 */
214 break;
215 }
216 return ret;
12
Returning value (loaded from 'ret'), which participates in a condition later
217}
218
219/*
220 * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
221 * function... It's safe, functions from cppsetup.c don't return here.
222 */
223static struct symhash *global_symbols = NULL((void*)0);
224
225char * isdefined( char *symbol )
226{
227 return hash_lookup( symbol, global_symbols );
228}
229
230/*
231 * Return type based on if the #if expression evaluates to 0
232 */
233int zero_value(char const *exp, struct symhash *symbols)
234{
235 global_symbols = symbols; /* HACK! see above */
236 if (cppsetup(exp))
237 return IFFALSE15;
238 else
239 return IF0;
240}
241
242void define( char *def, struct symhash **symbols )
243{
244 char *val;
245
246 /* Separate symbol name and its value */
247 val = def;
248 while (isalnum((unsigned char)*val)((*__ctype_b_loc ())[(int) (((unsigned char)*val))] & (unsigned
short int) _ISalnum)
|| *val == '_')
19
Assuming the condition is false
20
Assuming the condition is false
21
Loop condition is false. Execution continues on line 250
249 val++;
250 if (*val)
22
Assuming the condition is false
23
Taking false branch
251 *val++ = '\0';
252 while (*val == ' ' || *val == '\t')
24
Loop condition is false. Execution continues on line 255
253 val++;
254
255 if (!*val)
25
Taking true branch
256 val = "1";
257 hash_define( def, val, symbols );
26
Calling 'hash_define'
258}
259
260static int hash( char *str )
261{
262 /* Hash (Kernighan and Ritchie) */
263 unsigned int hashval = 0;
264
265 for ( ; *str; str++ )
266 {
267 hashval = ( hashval * SYMHASHSEED131 ) + ( *str );
268 }
269
270 return hashval & ( SYMHASHMEMBERS64 - 1 );
271}
272
273struct symhash *hash_copy( struct symhash *symbols )
274{
275 int i;
276 struct symhash *newsym;
277 if ( !symbols )
278 return NULL((void*)0);
279
280 newsym = (struct symhash *) malloc( sizeof( struct symhash ) );
281
282 for ( i = 0; i < SYMHASHMEMBERS64; ++i )
283 {
284 if ( !symbols->s_pairs[ i ] )
285 newsym->s_pairs[ i ] = NULL((void*)0);
286 else
287 {
288 struct pair *it = symbols->s_pairs[ i ];
289 struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) );
290 nw->p_name = it->p_name;
291 nw->p_value = it->p_value;
292 nw->p_next = NULL((void*)0);
293
294 while ( it->p_next )
295 {
296 nw->p_next = (struct pair*) malloc( sizeof( struct pair ) );
297 it = it->p_next;
298 nw = nw->p_next;
299 nw->p_name = it->p_name;
300 nw->p_value = it->p_value;
301 nw->p_next = NULL((void*)0);
302 }
303 }
304 }
305 return newsym;
306}
307
308void hash_free( struct symhash *symbols )
309{
310 int i;
311
312 if ( !symbols )
313 return;
314
315 for ( i = 0; i < SYMHASHMEMBERS64; ++i )
316 {
317 struct pair *it = symbols->s_pairs[ i ];
318 struct pair *next;
319 while ( it )
320 {
321 next = it->p_next;
322 free( it );
323 it = next;
324 }
325 }
326 free( symbols->s_pairs );
327}
328
329void hash_define( char *name, char const *val, struct symhash **symbols )
330{
331 int hashval;
332 struct pair *it;
333
334 if ( !symbols
26.1
'symbols' is non-null
)
27
Taking false branch
335 return;
336
337 /* Make space if it's needed */
338 if ( *symbols == NULL((void*)0) )
28
Assuming the condition is true
29
Taking true branch
339 {
340 int i;
341
342 *symbols = (struct symhash *) malloc( sizeof( struct symhash ) );
30
Value assigned to 'symbols'
343 if ( *symbols == NULL((void*)0) )
31
Assuming the condition is true
32
Taking true branch
344 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
345
346 for ( i = 0; i < SYMHASHMEMBERS64; ++i )
33
Loop condition is true. Entering loop body
347 (*symbols)->s_pairs[i] = NULL((void*)0);
34
Array access (via field 's_pairs') results in a null pointer dereference
348 }
349
350 hashval = hash( name );
351 it = (*symbols)->s_pairs[ hashval ];
352
353 /* Replace/insert the symbol */
354 if ( it == NULL((void*)0) )
355 {
356 it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) );
357 it->p_name = copy( name );
358 it->p_value = copy( val );
359 it->p_next = NULL((void*)0);
360 }
361 else if ( strcmp( it->p_name, name ) == 0 )
362 {
363 it->p_value = copy( val );
364 }
365 else
366 {
367 while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) )
368 {
369 it = it->p_next;
370 }
371 if ( it->p_next )
372 it->p_next->p_name = copy( name );
373 else
374 {
375 it->p_next = (struct pair*) malloc( sizeof( struct pair ) );
376 it->p_next->p_name = copy( name );
377 it->p_next->p_value = copy( val );
378 it->p_next->p_next = NULL((void*)0);
379 }
380 }
381}
382
383char *hash_lookup( char *symbol, struct symhash *symbols )
384{
385 struct pair *it;
386
387 if ( !symbols )
388 return NULL((void*)0);
389
390 it = symbols->s_pairs[ hash( symbol ) ];
391
392 while ( it && ( strcmp( it->p_name, symbol ) != 0 ) )
393 {
394 it = it->p_next;
395 }
396 if ( it )
397 return it->p_value;
398
399 return NULL((void*)0);
400}
401
402/* vim:set shiftwidth=4 softtabstop=4 expandtab: */