Bug Summary

File:home/maarten/src/libreoffice/core/soltools/cpp/_tokens.c
Warning:line 300, column 9
Null pointer passed to 1st parameter expecting 'nonnull'

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 _tokens.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/_tokens.c
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <assert.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <ctype.h>
25#if (defined(_WIN32) || defined(__IBMC__))
26#include <io.h>
27#else
28#include <unistd.h>
29#endif
30#include "cpp.h"
31
32
33static char wbuf[4 * OBS8092];
34static char *wbp = wbuf;
35static int EBCDIC_ExternTokenDetected = 0;
36static int EBCDIC_StartTokenDetected = 0;
37
38static unsigned char toLatin1[256] =
39{
40 0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f, 0x97, 0x8d,
41 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
42 0x9d, 0x0a, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d,
43 0x1e, 0x1f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1b,
44 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, 0x90, 0x91,
45 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9a, 0x9b,
46 0x14, 0x15, 0x9e, 0x1a, 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1,
47 0xe3, 0xe5, 0xe7, 0xf1, 0xa2, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
48 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef, 0xec, 0xdf,
49 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e, 0x2d, 0x2f, 0xc2, 0xc4,
50 0xc0, 0xc1, 0xc3, 0xc5, 0xc7, 0xd1, 0xa6, 0x2c, 0x25, 0x5f,
51 0x3e, 0x3f, 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
52 0xcc, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
53 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
54 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, 0xb0, 0x6a, 0x6b, 0x6c,
55 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8,
56 0xc6, 0xa4, 0xb5, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
57 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0x5b, 0xde, 0xae, 0xac, 0xa3,
58 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc, 0xbd, 0xbe, 0xdd, 0xa8,
59 0xaf, 0x5d, 0xb4, 0xd7, 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45,
60 0x46, 0x47, 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5,
61 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
62 0xb9, 0xfb, 0xfc, 0xf9, 0xfa, 0xff, 0x5c, 0xf7, 0x53, 0x54,
63 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2,
64 0xd3, 0xd5, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
65 0x38, 0x39, 0xb3, 0xdb, 0xdc, 0xd9, 0xda, 0x9f
66};
67
68#define MASK"\\x%x" "\\x%x"
69
70static int
71 memcpy_EBCDIC( char * pwbuf, uchar const *p, int len )
72{
73 int currpos = 0;
74 int processedchars = 0;
75
76 if( len == 0 )
77 return 0;
78
79 if( len == 1 )
80 {
81 *pwbuf = *p;
82 return 1;
83 }
84
85 /* copy spaces until " or ' */
86 while( (p[ processedchars ] != '\"') && (p[ processedchars ] != '\'') )
87 pwbuf[ currpos++ ] = p[ processedchars++ ];
88
89 /* copy first " or ' */
90 pwbuf[ currpos++ ] = p[ processedchars++ ];
91
92 /* convert all characters until " or ' */
93 while( processedchars < (len - 1) )
94 {
95 if( p[ processedchars ] == '\\' )
96 {
97 switch( p[ ++processedchars ] )
98 {
99 case 'n':
100 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1['\n'] );
101 processedchars++;
102 break;
103
104 case 't':
105 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1['\t'] );
106 processedchars++;
107 break;
108
109 case 'v':
110 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1['\v'] );
111 processedchars++;
112 break;
113
114 case 'b':
115 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1['\b'] );
116 processedchars++;
117 break;
118
119 case 'r':
120 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1['\r'] );
121 processedchars++;
122 break;
123
124 case 'f':
125 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1['\f'] );
126 processedchars++;
127 break;
128
129 case 'a':
130 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1['\a'] );
131 processedchars++;
132 break;
133
134 case '\\':
135 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1['\\'] );
136 processedchars++;
137 break;
138
139 case '?':
140 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1['\?'] );
141 processedchars++;
142 break;
143
144 case '\'':
145 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1['\''] );
146 processedchars++;
147 break;
148
149 case '"':
150 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1['\"'] );
151 processedchars++;
152 break;
153
154 /* octal coded character? -> copy */
155 case '0':
156 case '1':
157 case '2':
158 case '3':
159 case '4':
160 case '5':
161 case '6':
162 case '7':
163 {
164 int startpos = currpos;
165
166 pwbuf[ currpos++ ] = '\\';
167
168 while( p[ processedchars ] >= '0' && p[ processedchars ] <= '7' && (currpos < startpos + 4) )
169 pwbuf[ currpos++ ] = (unsigned char)p[ processedchars++ ];
170 break;
171 }
172
173 /* hex coded character? -> copy */
174 case 'x':
175 case 'X':
176 {
177 int startpos = currpos;
178
179 pwbuf[ currpos++ ] = '\\';
180 pwbuf[ currpos++ ] = 'x';
181 processedchars++;
182
183 while( isxdigit( p[ processedchars ] )((*__ctype_b_loc ())[(int) ((p[ processedchars ]))] & (unsigned
short int) _ISxdigit)
&& (currpos < startpos + 4) )
184 pwbuf[ currpos++ ] = (unsigned char)p[ processedchars++ ];
185 break;
186 }
187
188 }
189 }
190 else
191 currpos += sprintf( &pwbuf[ currpos ], MASK"\\x%x", toLatin1[p[ processedchars++ ]] );
192
193 }
194
195 /* copy last " or ' */
196 pwbuf[ currpos++ ] = p[ processedchars ];
197
198 return currpos;
199}
200
201void
202 maketokenrow(int size, Tokenrow * trp)
203{
204 trp->max = size;
205 if (size > 0)
2
Assuming 'size' is <= 0
3
Taking false branch
206 trp->bp = (Token *) domalloc(size * sizeof(Token));
207 else
208 trp->bp = NULL((void*)0);
4
Null pointer value stored to field 'bp'
209 trp->tp = trp->bp;
5
Null pointer value stored to field 'tp'
210 trp->lp = trp->bp;
211}
212
213Token *
214 growtokenrow(Tokenrow * trp)
215{
216 size_t ncur = trp->tp - trp->bp;
217 size_t nlast = trp->lp - trp->bp;
218
219 trp->max = 3 * trp->max / 2 + 1;
220 trp->bp = (Token *) realloc(trp->bp, trp->max * sizeof(Token));
221 assert(trp->bp)((void) sizeof ((trp->bp) ? 1 : 0), __extension__ ({ if (trp
->bp) ; else __assert_fail ("trp->bp", "/home/maarten/src/libreoffice/core/soltools/cpp/_tokens.c"
, 221, __extension__ __PRETTY_FUNCTION__); }))
; // realloc failure is OOM -> no point to handle
222 trp->lp = &trp->bp[nlast];
223 trp->tp = &trp->bp[ncur];
224 return trp->lp;
225}
226
227/*
228 * Compare a row of tokens, ignoring the content of WS; return !=0 if different
229 */
230int
231 comparetokens(Tokenrow * tr1, Tokenrow * tr2)
232{
233 Token *tp1, *tp2;
234
235 tp1 = tr1->tp;
236 tp2 = tr2->tp;
237 if (tr1->lp - tp1 != tr2->lp - tp2)
238 return 1;
239 for (; tp1 < tr1->lp; tp1++, tp2++)
240 {
241 if (tp1->type != tp2->type
242 || (tp1->wslen == 0) != (tp2->wslen == 0)
243 || tp1->len != tp2->len
244 || strncmp((char *) tp1->t, (char *) tp2->t, tp1->len) != 0)
245 return 1;
246 }
247 return 0;
248}
249
250/*
251 * replace ntok tokens starting at dtr->tp with the contents of str.
252 * tp ends up pointing just beyond the replacement.
253 * Canonical whitespace is assured on each side.
254 */
255void
256 insertrow(Tokenrow * dtr, int ntok, Tokenrow const * str)
257{
258 int nrtok = (int)rowlen(str)((str)->lp - (str)->bp);
259
260 dtr->tp += ntok;
261 adjustrow(dtr, nrtok - ntok);
262 dtr->tp -= ntok;
263 movetokenrow(dtr, str);
264 dtr->tp += nrtok;
265}
266
267/*
268 * make sure there is WS before trp->tp, if tokens might merge in the output
269 */
270void
271 makespace(Tokenrow * trp, Token const * ntp)
272{
273 uchar *tt;
274 Token *tp = trp->tp;
275
276 if (tp >= trp->lp)
277 return;
278
279 if (ntp->wslen)
280 {
281 tt = newstring(tp->t, tp->len, ntp->wslen);
282 strncpy((char *)tt, (char *)ntp->t - ntp->wslen, ntp->wslen);
283 tp->t = tt + ntp->wslen;
284 tp->wslen = ntp->wslen;
285 }
286}
287
288/*
289 * Copy an entire tokenrow into another, at tp.
290 * It is assumed that there is enough space.
291 * Not strictly conforming.
292 */
293void
294 movetokenrow(Tokenrow * dtr, Tokenrow const * str)
295{
296 size_t nby;
297
298 nby = (char *) str->lp - (char *) str->bp;
299 if (nby)
8
Assuming 'nby' is not equal to 0
9
Taking true branch
300 memmove(dtr->tp, str->bp, nby);
10
Null pointer passed to 1st parameter expecting 'nonnull'
301}
302
303/*
304 * Move the tokens in a row, starting at tr->tp, rightward by nt tokens;
305 * nt may be negative (left move).
306 * The row may need to be grown.
307 * Non-strictly conforming because of the (char *), but easily fixed
308 */
309void
310 adjustrow(Tokenrow * trp, int nt)
311{
312 size_t nby, size;
313
314 if (nt == 0)
315 return;
316 size = (trp->lp - trp->bp) + nt;
317 while (size > trp->max)
318 growtokenrow(trp);
319 nby = (char *) trp->lp - (char *) trp->tp;
320 if (nby)
321 memmove(trp->tp + nt, trp->tp, nby);
322 trp->lp += nt;
323}
324
325/*
326 * Copy a row of tokens into the destination holder, allocating
327 * the space for the contents. Return the destination.
328 */
329Tokenrow *
330 copytokenrow(Tokenrow * dtr, Tokenrow const * str)
331{
332 int len = (int)rowlen(str)((str)->lp - (str)->bp);
333
334 maketokenrow(len, dtr);
1
Calling 'maketokenrow'
6
Returning from 'maketokenrow'
335 movetokenrow(dtr, str);
7
Calling 'movetokenrow'
336 if (len != 0)
337 dtr->lp += len;
338 return dtr;
339}
340
341/*
342 * Produce a copy of a row of tokens. Start at trp->tp.
343 * The value strings are copied as well. The first token
344 * has WS available.
345 */
346Tokenrow *
347 normtokenrow(Tokenrow * trp)
348{
349 Token *tp;
350 Tokenrow *ntrp = new(Tokenrow)(Tokenrow *)domalloc(sizeof(Tokenrow));
351 int len;
352
353 len = (int)(trp->lp - trp->tp);
354 if (len <= 0)
355 len = 1;
356 maketokenrow(len, ntrp);
357 for (tp = trp->tp; tp < trp->lp; tp++)
358 {
359 *ntrp->lp = *tp;
360 if (tp->len)
361 {
362 ntrp->lp->t = newstring(tp->t, tp->len, 1);
363 *ntrp->lp->t++ = ' ';
364 if (tp->wslen)
365 ntrp->lp->wslen = 1;
366 }
367 ntrp->lp++;
368 }
369 if (ntrp->lp > ntrp->bp)
370 ntrp->bp->wslen = 0;
371 return ntrp;
372}
373
374/*
375 * Debugging
376 */
377void
378 peektokens(Tokenrow * trp, char *str)
379{
380 Token *tp;
381
382 tp = trp->tp;
383 flushout();
384 if (str)
385 fprintf(stderrstderr, "%s ", str);
386 if (tp < trp->bp || tp > trp->lp)
387 fprintf(stderrstderr, "(tp offset %ld) ", (long int) (tp - trp->bp));
388 for (tp = trp->bp; tp < trp->lp && tp < trp->bp + 32; tp++)
389 {
390 if (tp->type != NL)
391 {
392 int c = tp->t[tp->len];
393
394 tp->t[tp->len] = 0;
395 fprintf(stderrstderr, "%s", tp->t);
396 tp->t[tp->len] = (uchar) c;
397 }
398 fprintf(stderrstderr, tp == trp->tp ? "{%x*} " : "{%x} ", tp->type);
399 }
400 fprintf(stderrstderr, "\n");
401 fflush(stderrstderr);
402}
403
404void
405 puttokens(Tokenrow * trp)
406{
407 Token *tp;
408 int len;
409 uchar *p;
410
411 if (Vflag)
412 peektokens(trp, "");
413 tp = trp->bp;
414 for (; tp < trp->lp; tp++)
415 {
416 if (tp->type != NL)
417 {
418 len = (int)(tp->len + tp->wslen);
419 p = tp->t - tp->wslen;
420
421 /* add parameter check to delete operator? */
422 if( Dflag )
423 {
424 if( (tp->type == NAME) && (strncmp( (char*)p, "delete", len ) == 0) )
425 {
426 Token* ntp = tp;
427 ntp++;
428
429 if( ntp->type == NAME )
430 {
431 uchar* np = ntp->t - ntp->wslen;
432 int nlen = (int)(ntp->len + ntp->wslen);
433
434 memcpy(wbp, "if(", 3 );
435 wbp += 4;
436 memcpy(wbp, np, nlen );
437 wbp += nlen;
438 memcpy(wbp, ")", 1 );
439 wbp++;
440
441 memcpy(wbp, p, len);
442 }
443 }
444 }
445
446 /* EBCDIC to ANSI conversion requested? */
447 if( Aflag )
448 {
449 /* keyword __ToLatin1__ found? -> do conversion! */
450 if( EBCDIC_StartTokenDetected )
451 {
452 /* previous token was 'extern'? -> don't convert current token! */
453 if( EBCDIC_ExternTokenDetected )
454 {
455 EBCDIC_ExternTokenDetected = 0;
456 memcpy(wbp, p, len);
457 }
458 else
459 {
460 /* current token is keyword 'extern'? -> don't convert following token! */
461 if( (tp->wslen == 0) && (strncmp( (char*)p, "extern", len ) == 0) )
462 {
463 EBCDIC_ExternTokenDetected = 1;
464 memcpy(wbp, p, len);
465 }
466 else
467 {
468 /* token is string or char? -> process EBCDIC to ANSI conversion */
469 if ((tp->type == STRING) || (tp->type == CCON))
470 len = memcpy_EBCDIC(wbp, p, len);
471 else
472 memcpy(wbp, p, len);
473 }
474 }
475 }
476 else
477 /* keyword __ToLatin1__ found? -> don't copy keyword and start conversion */
478 if( (tp->type == NAME) && (strncmp( (char*)p, "__ToLatin1__", len) == 0) )
479 {
480 EBCDIC_StartTokenDetected = 1;
481 len = 0;
482 }
483 else
484 memcpy(wbp, p, len);
485 }
486 else
487 memcpy(wbp, p, len);
488
489 wbp += len;
490 }
491 else
492 *wbp++ = '\n';
493
494 if (wbp >= &wbuf[OBS8092])
495 {
496 if ( write(1, wbuf, OBS8092) != -1 ) {
497 if (wbp > &wbuf[OBS8092])
498 memmove(wbuf, wbuf + OBS8092, wbp - &wbuf[OBS8092]);
499 wbp -= OBS8092;
500 }
501 else exit(1);
502 }
503 }
504 trp->tp = tp;
505 if (cursource->fd == 0)
506 flushout();
507}
508
509void
510 flushout(void)
511{
512 if (wbp > wbuf)
513 {
514 if ( write(1, wbuf, (int)(wbp - wbuf)) != -1)
515 wbp = wbuf;
516 else
517 exit(1);
518 }
519}
520
521/*
522 * turn a row into just a newline
523 */
524void
525 setempty(Tokenrow * trp)
526{
527 trp->tp = trp->bp;
528 trp->lp = trp->bp + 1;
529 *trp->bp = nltoken;
530}
531
532/*
533 * generate a number
534 */
535char *
536 outnum(char *p, int n)
537{
538 if (n >= 10)
539 p = outnum(p, n / 10);
540 *p++ = (char) (n % 10 + '0');
541 return p;
542}
543
544/*
545 * allocate and initialize a new string from s, of length l, at offset o
546 * Null terminated.
547 */
548uchar *
549 newstring(uchar const * s, size_t l, size_t o)
550{
551 uchar *ns = (uchar *) domalloc(l + o + 1);
552
553 ns[l + o] = '\0';
554 return (uchar *) strncpy((char *) ns + o, (char *) s, l) - o;
555}
556
557/* vim:set shiftwidth=4 softtabstop=4 expandtab: */