Bug Summary

File:glib-utils.c
Warning:line 245, column 18
Out of bound memory access (access exceeds upper limit of memory block)

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 glib-utils.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 -pic-is-pie -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/src -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D GRAPA_RESOURCE_UI_PATH="/org/cafe/Grapa/ui" -D FR_PREFIX="/usr" -D FR_SYSCONFDIR="/usr/etc" -D FR_DATADIR="/usr/share" -D PRIVDATADIR="/usr/share/grapa/" -D FR_LIBDIR="/usr/lib" -D PKG_DATA_DIR="/usr/share/grapa" -D PIXMAPSDIR="/usr/share/pixmaps" -D GLADEDIR="" -D LOCALEDIR="/usr/share/locale" -D SHDIR="/usr/libexec/grapa/" -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/gio-unix-2.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/json-glib-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/libmount -I /usr/include/blkid -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/src -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-08-06-113338-51261-1 -x c glib-utils.c
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3/*
4 * Grapa
5 *
6 * Copyright (C) 2005 Free Software Foundation, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#include <config.h>
24#include <string.h>
25#include <stdio.h>
26#include <glib.h>
27#include <glib/gi18n.h>
28#include <glib/gprintf.h>
29#include <glib-object.h>
30#include "glib-utils.h"
31
32
33#define MAX_PATTERNS128 128
34
35
36/* gobject utils*/
37
38
39void
40_g_object_unref (gpointer object)
41{
42 if (object != NULL((void*)0))
43 g_object_unref (object);
44}
45
46
47/* string utils */
48
49gboolean
50strchrs (const char *str,
51 const char *chars)
52{
53 const char *c;
54 for (c = chars; *c != '\0'; c++)
55 if (strchr (str, *c) != NULL((void*)0))
56 return TRUE(!(0));
57 return FALSE(0);
58}
59
60
61char *
62str_substitute (const char *str,
63 const char *from_str,
64 const char *to_str)
65{
66 char **tokens;
67 int i;
68 GString *gstr;
69
70 if (str == NULL((void*)0))
71 return NULL((void*)0);
72
73 if (from_str == NULL((void*)0))
74 return g_strdup (str)g_strdup_inline (str);
75
76 if (strcmp (str, from_str) == 0)
77 return g_strdup (to_str)g_strdup_inline (to_str);
78
79 tokens = g_strsplit (str, from_str, -1);
80
81 gstr = g_string_new (NULL((void*)0));
82 for (i = 0; tokens[i] != NULL((void*)0); i++) {
83 gstr = g_string_append (gstr, tokens[i])(__builtin_constant_p (tokens[i]) ? __extension__ ({ const char
* const __val = (tokens[i]); g_string_append_len_inline (gstr
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (gstr
, tokens[i], (gssize) -1))
;
84 if ((to_str != NULL((void*)0)) && (tokens[i+1] != NULL((void*)0)))
85 gstr = g_string_append (gstr, to_str)(__builtin_constant_p (to_str) ? __extension__ ({ const char *
const __val = (to_str); g_string_append_len_inline (gstr, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (gstr, to_str
, (gssize) -1))
;
86 }
87
88 g_strfreev (tokens);
89
90 return g_string_free (gstr, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((gstr
), ((0))) : g_string_free_and_steal (gstr)) : (g_string_free)
((gstr), ((0))))
;
91}
92
93
94int
95strcmp_null_tolerant (const char *s1, const char *s2)
96{
97 if ((s1 == NULL((void*)0)) && (s2 == NULL((void*)0)))
98 return 0;
99 else if ((s1 != NULL((void*)0)) && (s2 == NULL((void*)0)))
100 return 1;
101 else if ((s1 == NULL((void*)0)) && (s2 != NULL((void*)0)))
102 return -1;
103 else
104 return strcmp (s1, s2);
105}
106
107
108/* counts how many characters to escape in @str. */
109static int
110count_chars_to_escape (const char *str,
111 const char *meta_chars)
112{
113 int meta_chars_n = strlen (meta_chars);
114 const char *s;
115 int n = 0;
116
117 for (s = str; *s != 0; s++) {
118 int i;
119 for (i = 0; i < meta_chars_n; i++)
120 if (*s == meta_chars[i]) {
121 n++;
122 break;
123 }
124 }
125 return n;
126}
127
128
129char*
130escape_str_common (const char *str,
131 const char *meta_chars,
132 const char prefix,
133 const char postfix)
134{
135 int meta_chars_n = strlen (meta_chars);
136 char *escaped;
137 int i, new_l, extra_chars = 0;
138 const char *s;
139 char *t;
140
141 if (str == NULL((void*)0))
142 return NULL((void*)0);
143
144 if (prefix)
145 extra_chars++;
146 if (postfix)
147 extra_chars++;
148
149 new_l = strlen (str) + (count_chars_to_escape (str, meta_chars) * extra_chars);
150 escaped = g_malloc (new_l + 1);
151
152 s = str;
153 t = escaped;
154 while (*s) {
155 gboolean is_bad = FALSE(0);
156 for (i = 0; (i < meta_chars_n) && !is_bad; i++)
157 is_bad = (*s == meta_chars[i]);
158 if (is_bad && prefix)
159 *t++ = prefix;
160 *t++ = *s++;
161 if (is_bad && postfix)
162 *t++ = postfix;
163 }
164 *t = 0;
165
166 return escaped;
167}
168
169
170/* escape with backslash the string @str. */
171char*
172escape_str (const char *str,
173 const char *meta_chars)
174{
175 return escape_str_common (str, meta_chars, '\\', 0);
176}
177
178
179static const char *
180g_utf8_strstr (const char *haystack, const char *needle)
181{
182 const char *s;
183 gsize i;
184 gsize haystack_len = g_utf8_strlen (haystack, -1);
185 gsize needle_len = g_utf8_strlen (needle, -1);
186 int needle_size = strlen (needle);
187
188 s = haystack;
189 for (i = 0; i <= haystack_len - needle_len; i++) {
190 if (strncmp (s, needle, needle_size) == 0)
191 return s;
192 s = g_utf8_next_char(s)(char *)((s) + g_utf8_skip[*(const guchar *)(s)]);
193 }
194
195 return NULL((void*)0);
196}
197
198
199static char**
200g_utf8_strsplit (const char *string,
201 const char *delimiter,
202 int max_tokens)
203{
204 GSList *string_list = NULL((void*)0), *slist;
205 char **str_array;
206 const char *s;
207 guint n = 0;
208 const char *remainder;
209
210 g_return_val_if_fail (string != NULL, NULL)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "string != NULL")
; return (((void*)0)); } } while (0)
;
5
Taking true branch
6
Loop condition is false. Exiting loop
211 g_return_val_if_fail (delimiter != NULL, NULL)do { if ((delimiter != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "delimiter != NULL"
); return (((void*)0)); } } while (0)
;
7
Taking true branch
8
Loop condition is false. Exiting loop
212 g_return_val_if_fail (delimiter[0] != '\0', NULL)do { if ((delimiter[0] != '\0')) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "delimiter[0] != '\\0'"
); return (((void*)0)); } } while (0)
;
9
Taking true branch
10
Loop condition is false. Exiting loop
213
214 if (max_tokens
10.1
'max_tokens' is >= 1
< 1)
11
Taking false branch
215 max_tokens = G_MAXINT2147483647;
216
217 remainder = string;
218 s = g_utf8_strstr (remainder, delimiter);
219 if (s != NULL((void*)0)) {
12
Assuming 's' is equal to NULL
13
Taking false branch
220 gsize delimiter_size = strlen (delimiter);
221
222 while (--max_tokens && (s != NULL((void*)0))) {
223 gsize size = s - remainder;
224 char *new_string;
225
226 new_string = g_new (char, size + 1)((char *) g_malloc_n ((size + 1), sizeof (char)));
227 strncpy (new_string, remainder, size);
228 new_string[size] = 0;
229
230 string_list = g_slist_prepend (string_list, new_string);
231 n++;
232 remainder = s + delimiter_size;
233 s = g_utf8_strstr (remainder, delimiter);
234 }
235 }
236 if (*string) {
14
Assuming the condition is true
15
Taking true branch
237 n++;
238 string_list = g_slist_prepend (string_list, g_strdup (remainder)g_strdup_inline (remainder));
239 }
240
241 str_array = g_new (char*, n + 1)((char* *) g_malloc_n ((n + 1), sizeof (char*)));
242
243 str_array[n--] = NULL((void*)0);
244 for (slist = string_list; slist; slist = slist->next)
16
Loop condition is true. Entering loop body
17
Loop condition is true. Entering loop body
245 str_array[n--] = slist->data;
18
Out of bound memory access (access exceeds upper limit of memory block)
246
247 g_slist_free (string_list);
248
249 return str_array;
250}
251
252
253static char*
254g_utf8_strchug (char *string)
255{
256 char *scan;
257 gunichar c;
258
259 g_return_val_if_fail (string != NULL, NULL)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "string != NULL")
; return (((void*)0)); } } while (0)
;
260
261 scan = string;
262 c = g_utf8_get_char (scan);
263 while (g_unichar_isspace (c)) {
264 scan = g_utf8_next_char (scan)(char *)((scan) + g_utf8_skip[*(const guchar *)(scan)]);
265 c = g_utf8_get_char (scan);
266 }
267
268 memmove (string, scan, strlen (scan) + 1);
269
270 return string;
271}
272
273
274static char*
275g_utf8_strchomp (char *string)
276{
277 char *scan;
278 gsize len;
279
280 g_return_val_if_fail (string != NULL, NULL)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "string != NULL")
; return (((void*)0)); } } while (0)
;
281
282 len = g_utf8_strlen (string, -1);
283
284 if (len == 0)
285 return string;
286
287 scan = g_utf8_offset_to_pointer (string, len - 1);
288
289 while (len--) {
290 gunichar c = g_utf8_get_char (scan);
291 if (g_unichar_isspace (c))
292 *scan = '\0';
293 else
294 break;
295 scan = g_utf8_find_prev_char (string, scan);
296 }
297
298 return string;
299}
300
301
302#define g_utf8_strstrip(string)g_utf8_strchomp (g_utf8_strchug (string)) g_utf8_strchomp (g_utf8_strchug (string))
303
304
305gboolean
306match_regexps (GRegex **regexps,
307 const char *string,
308 GRegexMatchFlags match_options)
309{
310 gboolean matched;
311 int i;
312
313 if ((regexps == NULL((void*)0)) || (regexps[0] == NULL((void*)0)))
314 return TRUE(!(0));
315
316 if (string == NULL((void*)0))
317 return FALSE(0);
318
319 matched = FALSE(0);
320 for (i = 0; regexps[i] != NULL((void*)0); i++)
321 if (g_regex_match (regexps[i], string, match_options, NULL((void*)0))) {
322 matched = TRUE(!(0));
323 break;
324 }
325
326 return matched;
327}
328
329
330void
331free_regexps (GRegex **regexps)
332{
333 int i;
334
335 if (regexps == NULL((void*)0))
336 return;
337
338 for (i = 0; regexps[i] != NULL((void*)0); i++)
339 g_regex_unref (regexps[i]);
340 g_free (regexps);
341}
342
343
344char **
345search_util_get_patterns (const char *pattern_string)
346{
347 char **patterns;
348 int i;
349
350 if (pattern_string == NULL((void*)0))
2
Assuming 'pattern_string' is not equal to NULL
3
Taking false branch
351 return NULL((void*)0);
352
353 patterns = g_utf8_strsplit (pattern_string, ";", MAX_PATTERNS128);
4
Calling 'g_utf8_strsplit'
354 for (i = 0; patterns[i] != NULL((void*)0); i++) {
355 char *p1, *p2;
356
357 p1 = g_utf8_strstrip (patterns[i])g_utf8_strchomp (g_utf8_strchug (patterns[i]));
358 p2 = str_substitute (p1, ".", "\\.");
359 patterns[i] = str_substitute (p2, "*", ".*");
360
361 g_free (p2);
362 g_free (p1);
363 }
364
365 return patterns;
366}
367
368
369GRegex **
370search_util_get_regexps (const char *pattern_string,
371 GRegexCompileFlags compile_options)
372{
373 char **patterns;
374 GRegex **regexps;
375 int i;
376
377 patterns = search_util_get_patterns (pattern_string);
1
Calling 'search_util_get_patterns'
378 if (patterns == NULL((void*)0))
379 return NULL((void*)0);
380
381 regexps = g_new0 (GRegex*, n_fields (patterns) + 1)((GRegex* *) g_malloc0_n ((n_fields (patterns) + 1), sizeof (
GRegex*)))
;
382 for (i = 0; patterns[i] != NULL((void*)0); i++)
383 regexps[i] = g_regex_new (patterns[i],
384 G_REGEX_OPTIMIZE | compile_options,
385 G_REGEX_MATCH_NOTEMPTY,
386 NULL((void*)0));
387 g_strfreev (patterns);
388
389 return regexps;
390}
391
392
393const char *
394eat_spaces (const char *line)
395{
396 if (line == NULL((void*)0))
397 return NULL((void*)0);
398 while ((*line == ' ') && (*line != 0))
399 line++;
400 return line;
401}
402
403
404char **
405split_line (const char *line,
406 int n_fields)
407{
408 char **fields;
409 const char *scan, *field_end;
410 int i;
411
412 fields = g_new0 (char *, n_fields + 1)((char * *) g_malloc0_n ((n_fields + 1), sizeof (char *)));
413 fields[n_fields] = NULL((void*)0);
414
415 scan = eat_spaces (line);
416 for (i = 0; i < n_fields; i++) {
417 if (scan == NULL((void*)0)) {
418 fields[i] = NULL((void*)0);
419 continue;
420 }
421 field_end = strchr (scan, ' ');
422 if (field_end != NULL((void*)0)) {
423 fields[i] = g_strndup (scan, field_end - scan);
424 scan = eat_spaces (field_end);
425 }
426 else if (i == n_fields - 1)
427 {
428 fields[i] = g_strdup (scan)g_strdup_inline (scan);
429 }
430 }
431
432 return fields;
433}
434
435
436const char *
437get_last_field (const char *line,
438 int last_field)
439{
440 const char *field;
441 int i;
442
443 if (line == NULL((void*)0))
444 return NULL((void*)0);
445
446 last_field--;
447 field = eat_spaces (line);
448 for (i = 0; i < last_field; i++) {
449 if (field == NULL((void*)0))
450 return NULL((void*)0);
451 field = strchr (field, ' ');
452 field = eat_spaces (field);
453 }
454
455 return field;
456}
457
458
459int
460n_fields (char **str_array)
461{
462 int i;
463
464 if (str_array == NULL((void*)0))
465 return 0;
466
467 i = 0;
468 while (str_array[i] != NULL((void*)0))
469 i++;
470 return i;
471}
472
473
474void
475debug (const char *file,
476 int line,
477 const char *function,
478 const char *format, ...)
479{
480#ifdef CAFE_ENABLE_DEBUG
481 va_list args;
482 char *str;
483
484 g_return_if_fail (format != NULL)do { if ((format != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "format != NULL")
; return; } } while (0)
;
485
486 va_start (args, format)__builtin_va_start(args, format);
487 str = g_strdup_vprintf (format, args);
488 va_end (args)__builtin_va_end(args);
489
490 g_fprintf (stderrstderr, "[FR] %s:%d (%s):\n\t%s\n", file, line, function, str);
491
492 g_free (str);
493#else /* ! DEBUG */
494#endif
495}
496
497
498void
499g_ptr_array_free_full (GPtrArray *array,
500 GFunc free_func,
501 gpointer user_data)
502{
503 g_ptr_array_foreach (array, free_func, user_data);
504 g_ptr_array_free (array, TRUE(!(0)));
505}
506
507
508GHashTable *static_strings = NULL((void*)0);
509
510
511const char *
512get_static_string (const char *s)
513{
514 const char *result;
515
516 if (s == NULL((void*)0))
517 return NULL((void*)0);
518
519 if (static_strings == NULL((void*)0))
520 static_strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL((void*)0));
521
522 if (! g_hash_table_lookup_extended (static_strings, s, (gpointer*) &result, NULL((void*)0))) {
523 result = g_strdup (s)g_strdup_inline (s);
524 g_hash_table_insert (static_strings,
525 (gpointer) result,
526 GINT_TO_POINTER (1)((gpointer) (glong) (1)));
527 }
528
529 return result;
530}
531
532
533char*
534g_uri_display_basename (const char *uri)
535{
536 char *e_name, *name;
537
538 e_name = g_filename_display_basename (uri);
539 name = g_uri_unescape_string (e_name, "");
540 g_free (e_name);
541
542 return name;
543}
544
545
546const gchar *
547_g_path_get_file_name (const gchar *file_name)
548{
549 register char *base;
550 register gssize last_char;
551
552 if (file_name == NULL((void*)0))
553 return NULL((void*)0);
554
555 if (file_name[0] == '\0')
556 return "";
557
558 last_char = strlen (file_name) - 1;
559
560 if (file_name [last_char] == G_DIR_SEPARATOR'/')
561 return "";
562
563 base = g_utf8_strrchr (file_name, -1, G_DIR_SEPARATOR'/');
564 if (! base)
565 return file_name;
566
567 return base + 1;
568}
569
570
571const char *
572_g_path_get_base_name (const char *path,
573 const char *base_dir,
574 gboolean junk_paths)
575{
576 size_t base_dir_len;
577 const char *base_path;
578
579 if (junk_paths)
580 return _g_path_get_file_name (path);
581
582
583 if (base_dir == NULL((void*)0))
584 return (path[0] == '/') ? path + 1 : path;
585
586 base_dir_len = strlen (base_dir);
587 if (strlen (path) < base_dir_len)
588 return NULL((void*)0);
589
590 base_path = path + base_dir_len;
591 if (path[0] != '/')
592 base_path -= 1;
593
594 return base_path;
595}
596