Bug Summary

File:backend/dvi/mdvi-lib/util.c
Warning:line 339, column 27
Null pointer passed to 1st parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name util.c -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 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/backend/dvi/mdvi-lib -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I ../../.. -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/backend/dvi/mdvi-lib -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-02-17-124057-54187-1 -x c util.c
1/*
2 * Copyright (C) 2000, Matias Atria
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#include <config.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <stdarg.h>
23#include <string.h>
24#include <time.h>
25#include <sys/stat.h>
26#include <errno(*__errno_location ()).h>
27#include <unistd.h>
28
29#include "common.h"
30#include "private.h"
31
32static char *const messages[] = {
33 _G("Ooops!")"Ooops!",
34 _G("Aieeeee!!")"Aieeeee!!",
35 _G("Ouch!")"Ouch!",
36 _G("Houston, we have a problem")"Houston, we have a problem",
37 _G("3.. 2.. 1.. BOOM!")"3.. 2.. 1.. BOOM!",
38 _G("I'm history")"I'm history",
39 _G("I'm going down")"I'm going down",
40 _G("I smell a rat")"I smell a rat"
41};
42#define NMSGS(sizeof(messages) / sizeof(char *)) (sizeof(messages) / sizeof(char *))
43
44static FILE *logfile = NULL((void*)0);
45static int _mdvi_log_level;
46
47int mdvi_set_logfile(const char *filename);
48int mdvi_set_logstream(FILE *file);
49int mdvi_set_loglevel(int level);
50
51static void vputlog(int level, const char *head, const char *format, va_list ap)
52{
53 if(logfile != NULL((void*)0) && _mdvi_log_level >= level) {
54 if(head != NULL((void*)0))
55 fprintf(logfile, "%s: ", head);
56 vfprintf(logfile, format, ap);
57 }
58}
59
60int mdvi_set_logfile(const char *filename)
61{
62 FILE *f = NULL((void*)0);
63
64 if(filename && (f = fopenkpse_fopen_trace(filename, "w")) == NULL((void*)0))
65 return -1;
66 if(logfile != NULL((void*)0) && !isatty(fileno(logfile))) {
67 fclosekpse_fclose_trace(logfile);
68 logfile = NULL((void*)0);
69 }
70 if(filename)
71 logfile = f;
72 return 0;
73}
74
75int mdvi_set_logstream(FILE *file)
76{
77 if(logfile && !isatty(fileno(logfile))) {
78 fclosekpse_fclose_trace(logfile);
79 logfile = NULL((void*)0);
80 }
81 logfile = file;
82 return 0;
83}
84
85int mdvi_set_loglevel(int level)
86{
87 int old = _mdvi_log_level;
88
89 _mdvi_log_level = level;
90 return old;
91}
92
93#ifndef NODEBUG
94Uint32 _mdvi_debug_mask = 0;
95
96void __debug(int mask, const char *format, ...)
97{
98 va_list ap;
99
100 va_start(ap, format)__builtin_va_start(ap, format);
101 if(_mdvi_debug_mask & mask) {
102 if(!DEBUGGING(SILENT)(_mdvi_debug_mask & (1 << 31))) {
103 fprintf(stderrstderr, "Debug: ");
104 vfprintf(stderrstderr, format, ap);
105 fflush(stderrstderr);
106 }
107#ifndef __GNUC__4
108 /* let's be portable */
109 va_end(ap)__builtin_va_end(ap);
110 va_start(ap, format)__builtin_va_start(ap, format);
111#endif
112 vputlog(LOG_DEBUG3, "Debug", format, ap);
113 }
114 va_end(ap)__builtin_va_end(ap);
115}
116#endif
117
118void mdvi_message(const char *format, ...)
119{
120 va_list ap;
121
122 va_start(ap, format)__builtin_va_start(ap, format);
123 if(_mdvi_log_level >= LOG_INFO0) {
124 fprintf(stderrstderr, "%s: ", program_name);
125 vfprintf(stderrstderr, format, ap);
126#ifndef __GNUC__4
127 va_end(ap)__builtin_va_end(ap);
128 va_start(ap, format)__builtin_va_start(ap, format);
129#endif
130 }
131 vputlog(LOG_INFO0, NULL((void*)0), format, ap);
132 va_end(ap)__builtin_va_end(ap);
133}
134
135void mdvi_crash(const char *format, ...)
136{
137 va_list ap;
138
139 va_start(ap, format)__builtin_va_start(ap, format);
140 fprintf(stderrstderr, "%s: %s: ",
141 program_name,
142 gettext(messages[(int)time(NULL((void*)0)) % NMSGS(sizeof(messages) / sizeof(char *))]));
143 vfprintf(stderrstderr, format, ap);
144#ifndef __GNUC__4
145 /* let's be portable */
146 va_end(ap)__builtin_va_end(ap);
147 va_start(ap, format)__builtin_va_start(ap, format);
148#endif
149 vputlog(LOG_ERROR2, _("Crashing")gettext("Crashing"), format, ap);
150 va_end(ap)__builtin_va_end(ap);
151 abort();
152}
153
154void mdvi_error(const char *format, ...)
155{
156 va_list ap;
157
158 va_start(ap, format)__builtin_va_start(ap, format);
159 fprintf(stderrstderr, _("%s: Error: ")gettext("%s: Error: "), program_name);
160 vfprintf(stderrstderr, format, ap);
161#ifndef __GNUC__4
162 /* let's be portable */
163 va_end(ap)__builtin_va_end(ap);
164 va_start(ap, format)__builtin_va_start(ap, format);
165#endif
166 vputlog(LOG_ERROR2, _("Error")gettext("Error"), format, ap);
167 va_end(ap)__builtin_va_end(ap);
168}
169
170void mdvi_warning(const char *format, ...)
171{
172 va_list ap;
173
174 va_start(ap, format)__builtin_va_start(ap, format);
175 fprintf(stderrstderr, _("%s: Warning: ")gettext("%s: Warning: "), program_name);
176 vfprintf(stderrstderr, format, ap);
177#ifndef __GNUC__4
178 /* let's be portable */
179 va_end(ap)__builtin_va_end(ap);
180 va_start(ap, format)__builtin_va_start(ap, format);
181#endif
182 vputlog(LOG_WARN1, _("Warning")gettext("Warning"), format, ap);
183 va_end(ap)__builtin_va_end(ap);
184}
185
186void mdvi_fatal(const char *format, ...)
187{
188 va_list ap;
189
190 va_start(ap, format)__builtin_va_start(ap, format);
191 fprintf(stderrstderr, _("%s: Fatal: ")gettext("%s: Fatal: "), program_name);
192 vfprintf(stderrstderr, format, ap);
193#ifndef __GNUC__4
194 /* let's be portable */
195 va_end(ap)__builtin_va_end(ap);
196 va_start(ap, format)__builtin_va_start(ap, format);
197#endif
198 vputlog(LOG_ERROR2, _("Fatal")gettext("Fatal"), format, ap);
199 va_end(ap)__builtin_va_end(ap);
200#ifndef NODEBUG
201 abort();
202#else
203 exit(EXIT_FAILURE1);
204#endif
205}
206
207void *mdvi_malloc(size_t nelems)
208{
209 void *ptr = malloc(nelems);
210
211 if(ptr == NULL((void*)0))
212 mdvi_fatal(_("out of memory allocating %u bytes\n")gettext("out of memory allocating %u bytes\n"),
213 (unsigned)nelems);
214 return ptr;
215}
216
217void *mdvi_realloc(void *data, size_t newsize)
218{
219 void *ptr;
220
221 if(newsize == 0)
222 mdvi_crash(_("attempted to reallocate with zero size\n")gettext("attempted to reallocate with zero size\n"));
223 ptr = realloc(data, newsize);
224 if(ptr == NULL((void*)0))
225 mdvi_fatal(_("failed to reallocate %u bytes\n")gettext("failed to reallocate %u bytes\n"), (unsigned)newsize);
226 return ptr;
227}
228
229void *mdvi_calloc(size_t nmemb, size_t size)
230{
231 void *ptr;
232
233 if(nmemb == 0)
234 mdvi_crash(_("attempted to callocate 0 members\n")gettext("attempted to callocate 0 members\n"));
235 if(size == 0)
236 mdvi_crash(_("attempted to callocate %u members with size 0\n")gettext("attempted to callocate %u members with size 0\n"),
237 (unsigned)nmemb);
238 ptr = calloc(nmemb, size);
239 if(ptr == 0)
240 mdvi_fatal(_("failed to allocate %ux%u bytes\n")gettext("failed to allocate %ux%u bytes\n"),
241 (unsigned)nmemb, (unsigned)size);
242 return ptr;
243}
244
245void mdvi_free(void *ptr)
246{
247 if(ptr == NULL((void*)0))
248 mdvi_crash(_("attempted to free NULL pointer\n")gettext("attempted to free NULL pointer\n"));
249 free(ptr);
250}
251
252char *mdvi_strdup(const char *string)
253{
254 int length;
255 char *ptr;
256
257 length = strlen(string) + 1;
258 ptr = (char *)mdvi_malloc(length);
259 memcpy(ptr, string, length)bcopy ((string), (ptr), (length));
260 return ptr;
261}
262
263/* `to' should have room for length+1 bytes */
264char *mdvi_strncpy(char *to, const char *from, size_t length)
265{
266 strncpy(to, from, length);
267 to[length] = '\0';
268 return to;
269}
270
271char *mdvi_strndup(const char *string, size_t length)
272{
273 int n;
274 char *ptr;
275
276 n = strlen(string);
277 if(n > length)
278 n = length;
279 ptr = (char *)mdvi_malloc(n + 1);
280 memcpy(ptr, string, n)bcopy ((string), (ptr), (n));
281 return ptr;
282}
283
284void *mdvi_memdup(const void *data, size_t length)
285{
286 void *ptr = mdvi_malloc(length);
287
288 memcpy(ptr, data, length)bcopy ((data), (ptr), (length));
289 return ptr;
290}
291
292char *mdvi_strrstr (const char *haystack, const char *needle)
293{
294 size_t i;
295 size_t needle_len;
296 size_t haystack_len;
297 const char *p;
298
299 needle_len = strlen (needle);
300 haystack_len = strlen (haystack);
301
302 if (needle_len == 0)
303 return NULL((void*)0);
304
305 if (haystack_len < needle_len)
306 return (char *)haystack;
307
308 p = haystack + haystack_len - needle_len;
309 while (p >= haystack) {
310 for (i = 0; i < needle_len; i++)
311 if (p[i] != needle[i])
312 goto next;
313
314 return (char *)p;
315
316 next:
317 p--;
318 }
319
320 return NULL((void*)0);
321}
322
323char *mdvi_build_path_from_cwd (const char *path)
324{
325 char *ptr;
326 char *buf = NULL((void*)0);
327 size_t buf_size = 512;
328
329 while (1) {
1
Loop condition is true. Entering loop body
330 buf = mdvi_realloc (buf, buf_size);
331 if ((ptr = getcwd (buf, buf_size)) == NULL((void*)0) && errno(*__errno_location ()) == ERANGE34) {
2
Value assigned to 'ptr'
3
Assuming pointer value is null
4
Assuming the condition is false
5
Taking false branch
332 buf_size *= 2;
333 } else {
334 buf = ptr;
6
Null pointer value stored to 'buf'
335 break;
336 }
337 }
338
339 buf = mdvi_realloc (buf, strlen (buf) + strlen (path) + 2);
7
Execution continues on line 339
8
Null pointer passed to 1st parameter expecting 'nonnull'
340 strcat (buf, "/");
341 strncat (buf, path, strlen (path));
342
343 return buf;
344}
345
346double unit2pix_factor(const char *spec)
347{
348 double val;
349 double factor;
350 const char *p, *q;
351 static const char *units = "incmmmmtptpcddccspbpftydcs";
352
353 val = 0.0;
354
355 for(p = spec; *p >= '0' && *p <= '9'; p++)
356 val = 10.0 * val + (double)(*p - '0');
357 if(*p == '.') {
358 p++;
359 factor = 0.1;
360 while(*p && *p >= '0' && *p <= '9') {
361 val += (*p++ - '0') * factor;
362 factor = factor * 0.1;
363 }
364 }
365 factor = 1.0;
366 for(q = units; *q; q += 2) {
367 if(p[0] == q[0] && p[1] == q[1])
368 break;
369 }
370 switch((int)(q - units)) {
371 /*in*/ case 0: factor = 1.0; break;
372 /*cm*/ case 2: factor = 1.0 / 2.54; break;
373 /*mm*/ case 4: factor = 1.0 / 25.4; break;
374 /*mt*/ case 6: factor = 1.0 / 0.0254; break;
375 /*pt*/ case 8: factor = 1.0 / 72.27; break;
376 /*pc*/ case 10: factor = 12.0 / 72.27; break;
377 /*dd*/ case 12: factor = (1238.0 / 1157.0) / 72.27; break;
378 /*cc*/ case 14: factor = 12 * (1238.0 / 1157.0) / 72.27; break;
379 /*sp*/ case 16: factor = 1.0 / (72.27 * 65536); break;
380 /*bp*/ case 18: factor = 1.0 / 72.0; break;
381 /*ft*/ case 20: factor = 12.0; break;
382 /*yd*/ case 22: factor = 36.0; break;
383 /*cs*/ case 24: factor = 1.0 / 72000.0; break;
384 default: factor = 1.0;
385 }
386 return factor * val;
387}
388
389int unit2pix(int dpi, const char *spec)
390{
391 double factor = unit2pix_factor(spec);
392
393 return (int)(factor * dpi + 0.5);
394}
395
396Ulong get_mtime(int fd)
397{
398 struct stat st;
399
400 if(fstat(fd, &st) == 0)
401 return (Ulong)st.st_mtimest_mtim.tv_sec;
402 return 0;
403}
404
405char *xstradd(char *dest, size_t *size, size_t n, const char *src, size_t m)
406{
407 if(m == 0)
408 m = strlen(src);
409 if(n + m >= *size) {
410 dest = mdvi_realloc(dest, n + m + 1);
411 *size = n + m + 1;
412 }
413 memcpy(dest + n, src, m)bcopy ((src), (dest + n), (m));
414 dest[n + m] = 0;
415 return dest;
416}
417
418char *getword(char *string, const char *delim, char **end)
419{
420 char *ptr;
421 char *word;
422
423 /* skip leading delimiters */
424 for(ptr = string; *ptr && strchr(delim, *ptr); ptr++);
425
426 if(*ptr == 0)
427 return NULL((void*)0);
428 word = ptr++;
429 /* skip non-delimiters */
430 while(*ptr && !strchr(delim, *ptr))
431 ptr++;
432 *end = (char *)ptr;
433 return word;
434}
435
436char *getstring(char *string, const char *delim, char **end)
437{
438 char *ptr;
439 char *word;
440 int quoted = 0;
441
442 /* skip leading delimiters */
443 for(ptr = string; *ptr && strchr(delim, *ptr); ptr++);
444
445 if(ptr == NULL((void*)0))
446 return NULL((void*)0);
447 quoted = (*ptr == '"');
448 if(quoted)
449 for(word = ++ptr; *ptr && *ptr != '"'; ptr++);
450 else
451 for(word = ptr; *ptr && !strchr(delim, *ptr); ptr++);
452 *end = (char *)ptr;
453 return word;
454}
455
456static long pow2(size_t n)
457{
458 long x = 8; /* don't bother allocating less than this */
459
460 while(x < n)
461 x <<= 1L;
462 return x;
463}
464
465void dstring_init(Dstring *dstr)
466{
467 dstr->data = NULL((void*)0);
468 dstr->size = 0;
469 dstr->length = 0;
470}
471
472int dstring_append(Dstring *dstr, const char *string, int len)
473{
474 if(len < 0)
475 len = strlen(string);
476 if(len) {
477 if(dstr->length + len >= dstr->size) {
478 dstr->size = pow2(dstr->length + len + 1);
479 dstr->data = mdvi_realloc(dstr->data, dstr->size);
480 }
481 memcpy(dstr->data + dstr->length, string, len)bcopy ((string), (dstr->data + dstr->length), (len));
482 dstr->length += len;
483 dstr->data[dstr->length] = 0;
484 } else if(dstr->size == 0) {
485 ASSERT(dstr->data == NULL)do { if(!(dstr->data == ((void*)0))) mdvi_crash("%s:%d: Assertion %s failed\n"
, "util.c", 485, "dstr->data == NULL"); } while(0)
;
486 dstr->size = 8;
487 dstr->data = mdvi_malloc(8);
488 dstr->data[0] = 0;
489 }
490
491 return dstr->length;
492}
493
494int dstring_copy(Dstring *dstr, int pos, const char *string, int len)
495{
496 ASSERT(pos >= 0)do { if(!(pos >= 0)) mdvi_crash("%s:%d: Assertion %s failed\n"
, "util.c", 496, "pos >= 0"); } while(0)
;
497 if(len < 0)
498 len = strlen(string);
499 if(len) {
500 if(pos + len >= dstr->length) {
501 dstr->length = pos;
502 return dstring_append(dstr, string, len);
503 }
504 memcpy(dstr->data + pos, string, len)bcopy ((string), (dstr->data + pos), (len));
505 }
506 return dstr->length;
507}
508
509int dstring_insert(Dstring *dstr, int pos, const char *string, int len)
510{
511 ASSERT(pos >= 0)do { if(!(pos >= 0)) mdvi_crash("%s:%d: Assertion %s failed\n"
, "util.c", 511, "pos >= 0"); } while(0)
;
512 if(pos == dstr->length)
513 return dstring_append(dstr, string, len);
514 if(len < 0)
515 len = strlen(string);
516 if(len) {
517 if(dstr->length + len >= dstr->size) {
518 dstr->size = pow2(dstr->length + len + 1);
519 dstr->data = mdvi_realloc(dstr->data, dstr->size);
520 }
521 /* make room */
522 memmove(dstr->data + pos, dstr->data + pos + len, len);
523 /* now copy */
524 memcpy(dstr->data + pos, string, len)bcopy ((string), (dstr->data + pos), (len));
525 dstr->length += len;
526 dstr->data[dstr->length] = 0;
527 }
528 return dstr->length;
529}
530
531int dstring_new(Dstring *dstr, const char *string, int len)
532{
533 if(len < 0)
534 len = strlen(string);
535 if(len) {
536 dstr->size = pow2(len + 1);
537 dstr->data = mdvi_malloc(dstr->size * len);
538 memcpy(dstr->data, string, len)bcopy ((string), (dstr->data), (len));
539 } else
540 dstring_init(dstr);
541 return dstr->length;
542}
543
544void dstring_reset(Dstring *dstr)
545{
546 if(dstr->data)
547 mdvi_free(dstr->data);
548 dstring_init(dstr);
549}
550