Bug Summary

File:src/eoc-util.c
Warning:line 302, column 11
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 eoc-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/src -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -I . -I .. -I ../jpegutils -I ../cut-n-paste/toolbar-editor -D G_LOG_DOMAIN="EOC" -D EOC_DATA_DIR="/usr/local/share/eoc" -D EOC_LOCALE_DIR="/usr/local/share/locale" -D EOC_PLUGIN_DIR="/usr/local/lib/eoc/plugins" -D LIBDIR="/usr/local/lib" -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -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/gio-unix-2.0 -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/cafe-desktop-2.0 -I /usr/include/startup-notification-1.0 -I /usr/include/dconf -I /usr/include/ctk-3.0/unix-print -I /usr/local/include/libbean-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/exempi-2.0 -I /usr/include/librsvg-2.0 -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/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-01-10-161402-32287-1 -x c eoc-util.c
1/* Eye Of Cafe - General Utilities
2 *
3 * Copyright (C) 2006 The Free Software Foundation
4 *
5 * Author: Lucas Rocha <lucasr@gnome.org>
6 *
7 * Based on code by:
8 * - Jens Finke <jens@gnome.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24
25#ifdef HAVE_CONFIG_H1
26#include "config.h"
27#endif
28
29#include <sys/time.h>
30#ifdef HAVE_STRPTIME1
31#define _XOPEN_SOURCE
32#endif /* HAVE_STRPTIME */
33
34#include <time.h>
35
36#include "eoc-util.h"
37
38#include <errno(*__errno_location ()).h>
39#include <string.h>
40#include <glib.h>
41#include <glib/gprintf.h>
42#include <glib/gstdio.h>
43#include <ctk/ctk.h>
44#include <gio/gio.h>
45#include <glib/gi18n.h>
46
47void
48eoc_util_show_help (const gchar *section, CtkWindow *parent)
49{
50 GError *error = NULL((void*)0);
51 gchar *uri = NULL((void*)0);
52
53 if (section)
54 uri = g_strdup_printf ("help:eoc/%s", section);
55
56 ctk_show_uri_on_window (parent, ((uri != NULL((void*)0)) ? uri : "help:eoc"),
57 ctk_get_current_event_time (), &error);
58
59 g_free (uri);
60
61 if (error) {
62 CtkWidget *dialog;
63
64 dialog = ctk_message_dialog_new (parent,
65 0,
66 CTK_MESSAGE_ERROR,
67 CTK_BUTTONS_OK,
68 _("Could not display help for Eye of CAFE")gettext ("Could not display help for Eye of CAFE"));
69
70 ctk_message_dialog_format_secondary_text (CTK_MESSAGE_DIALOG (dialog)((((CtkMessageDialog*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((dialog)), ((ctk_message_dialog_get_type ())
)))))
,
71 "%s", error->message);
72
73 g_signal_connect_swapped (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
ctk_widget_destroy))), (dialog), ((void*)0), G_CONNECT_SWAPPED
)
74 G_CALLBACK (ctk_widget_destroy),g_signal_connect_data ((dialog), ("response"), (((GCallback) (
ctk_widget_destroy))), (dialog), ((void*)0), G_CONNECT_SWAPPED
)
75 dialog)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
ctk_widget_destroy))), (dialog), ((void*)0), G_CONNECT_SWAPPED
)
;
76 ctk_widget_show (dialog);
77
78 g_error_free (error);
79 }
80}
81
82gchar *
83eoc_util_make_valid_utf8 (const gchar *str)
84{
85 GString *string;
86 const char *remainder, *invalid;
87 int remaining_bytes, valid_bytes;
88
89 string = NULL((void*)0);
90 remainder = str;
91 remaining_bytes = strlen (str);
92
93 while (remaining_bytes != 0) {
94 if (g_utf8_validate (remainder, remaining_bytes, &invalid)) {
95 break;
96 }
97
98 valid_bytes = invalid - remainder;
99
100 if (string == NULL((void*)0)) {
101 string = g_string_sized_new (remaining_bytes);
102 }
103
104 g_string_append_len (string, remainder, valid_bytes)g_string_append_len_inline (string, remainder, valid_bytes);
105 g_string_append_c (string, '?')g_string_append_c_inline (string, '?');
106
107 remaining_bytes -= valid_bytes + 1;
108 remainder = invalid + 1;
109 }
110
111 if (string == NULL((void*)0)) {
112 return g_strdup (str)g_strdup_inline (str);
113 }
114
115 g_string_append (string, remainder)(__builtin_constant_p (remainder) ? __extension__ ({ const char
* const __val = (remainder); g_string_append_len_inline (string
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (string
, remainder, (gssize) -1))
;
116 g_string_append (string, _(" (invalid Unicode)"))(__builtin_constant_p (gettext (" (invalid Unicode)")) ? __extension__
({ const char * const __val = (gettext (" (invalid Unicode)"
)); g_string_append_len_inline (string, __val, (__val != ((void
*)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1)
; }) : g_string_append_len_inline (string, gettext (" (invalid Unicode)"
), (gssize) -1))
;
117
118 g_assert (g_utf8_validate (string->str, -1, NULL))do { if (g_utf8_validate (string->str, -1, ((void*)0))) ; else
g_assertion_message_expr ("EOC", "eoc-util.c", 118, ((const char
*) (__func__)), "g_utf8_validate (string->str, -1, NULL)")
; } while (0)
;
119
120 return g_string_free (string, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((string
), ((0))) : g_string_free_and_steal (string)) : (g_string_free
) ((string), ((0))))
;
121}
122
123GSList*
124eoc_util_parse_uri_string_list_to_file_list (const gchar *uri_list)
125{
126 GSList* file_list = NULL((void*)0);
127 gsize i = 0;
128 gchar **uris;
129
130 uris = g_uri_list_extract_uris (uri_list);
131
132 while (uris[i] != NULL((void*)0)) {
133 file_list = g_slist_append (file_list, g_file_new_for_uri (uris[i]));
134 i++;
135 }
136
137 g_strfreev (uris);
138
139 return file_list;
140}
141
142GSList*
143eoc_util_string_list_to_file_list (GSList *string_list)
144{
145 GSList *it = NULL((void*)0);
146 GSList *file_list = NULL((void*)0);
147
148 for (it = string_list; it != NULL((void*)0); it = it->next) {
149 char *uri_str;
150
151 uri_str = (gchar *) it->data;
152
153 file_list = g_slist_prepend (file_list,
154 g_file_new_for_uri (uri_str));
155 }
156
157 return g_slist_reverse (file_list);
158}
159
160GSList*
161eoc_util_strings_to_file_list (gchar **strings)
162{
163 int i;
164 GSList *file_list = NULL((void*)0);
165
166 for (i = 0; strings[i]; i++) {
167 file_list = g_slist_prepend (file_list,
168 g_file_new_for_uri (strings[i]));
169 }
170
171 return g_slist_reverse (file_list);
172}
173
174GSList*
175eoc_util_string_array_to_list (const gchar **files, gboolean create_uri)
176{
177 gint i;
178 GSList *list = NULL((void*)0);
179
180 if (files == NULL((void*)0)) return list;
181
182 for (i = 0; files[i]; i++) {
183 char *str;
184
185 if (create_uri) {
186 GFile *file;
187
188 file = g_file_new_for_commandline_arg (files[i]);
189 str = g_file_get_uri (file);
190
191 g_object_unref (file);
192 } else {
193 str = g_strdup (files[i])g_strdup_inline (files[i]);
194 }
195
196 if (str) {
197 list = g_slist_prepend (list, g_strdup (str)g_strdup_inline (str));
198 g_free (str);
199 }
200 }
201
202 return g_slist_reverse (list);
203}
204
205gchar **
206eoc_util_string_array_make_absolute (gchar **files)
207{
208 int i;
209 int size;
210 gchar **abs_files;
211 GFile *file;
212
213 if (files == NULL((void*)0))
214 return NULL((void*)0);
215
216 size = g_strv_length (files);
217
218 /* Ensure new list is NULL-terminated */
219 abs_files = g_new0 (gchar *, size+1)((gchar * *) g_malloc0_n ((size+1), sizeof (gchar *)));
220
221 for (i = 0; i < size; i++) {
222 file = g_file_new_for_commandline_arg (files[i]);
223 abs_files[i] = g_file_get_uri (file);
224
225 g_object_unref (file);
226 }
227
228 return abs_files;
229}
230
231static gchar *dot_dir = NULL((void*)0);
232
233static gboolean
234ensure_dir_exists (const char *dir)
235{
236 if (g_file_test (dir, G_FILE_TEST_IS_DIR))
237 return TRUE(!(0));
238
239 if (g_mkdir_with_parents (dir, 0700) == 0)
240 return TRUE(!(0));
241
242 if (errno(*__errno_location ()) == EEXIST17)
243 return g_file_test (dir, G_FILE_TEST_IS_DIR);
244
245 g_warning ("Failed to create directory %s: %s", dir, strerror (errno(*__errno_location ())));
246 return FALSE(0);
247}
248
249const gchar *
250eoc_util_dot_dir (void)
251{
252 if (dot_dir == NULL((void*)0)) {
253 gboolean exists;
254
255 dot_dir = g_build_filename(g_get_user_config_dir(), "cafe", "eoc", NULL((void*)0));
256
257 exists = ensure_dir_exists (dot_dir);
258
259 if (G_UNLIKELY (!exists)(!exists)) {
260 static gboolean printed_warning = FALSE(0);
261
262 if (!printed_warning) {
263 g_warning ("EOC could not save some of your preferences in its settings directory due to a file with the same name (%s) blocking its creation. Please remove that file, or move it away.", dot_dir);
264 printed_warning = TRUE(!(0));
265 }
266 dot_dir = NULL((void*)0);
267 return NULL((void*)0);
268 }
269 }
270
271 return dot_dir;
272}
273
274/* Based on eel_filename_strip_extension() */
275
276/**
277 * eoc_util_filename_get_extension:
278 * @filename: a filename
279 *
280 * Returns a reasonably good guess of the file extension of @filename.
281 *
282 * Returns: a newly allocated string with the file extension of @filename.
283 **/
284char *
285eoc_util_filename_get_extension (const char * filename)
286{
287 char *begin, *begin2;
288
289 if (filename == NULL((void*)0)) {
1
Assuming 'filename' is not equal to NULL
2
Taking false branch
290 return NULL((void*)0);
291 }
292
293 begin = strrchr (filename, '.');
294
295 if (begin && begin != filename) {
3
Assuming 'begin' is non-null
4
Assuming 'begin' is not equal to 'filename'
296 if (strcmp (begin, ".gz") == 0 ||
297 strcmp (begin, ".bz2") == 0 ||
298 strcmp (begin, ".sit") == 0 ||
299 strcmp (begin, ".Z") == 0) {
300 begin2 = begin - 1;
301 while (begin2 > filename &&
5
Assuming 'begin2' is > 'filename'
302 *begin2 != '.') {
6
Out of bound memory access (access exceeds upper limit of memory block)
303 begin2--;
304 }
305 if (begin2 != filename) {
306 begin = begin2;
307 }
308 }
309 begin ++;
310 } else {
311 return NULL((void*)0);
312 }
313
314 return g_strdup (begin)g_strdup_inline (begin);
315}
316
317
318/**
319 * eoc_util_file_is_persistent:
320 * @file: a #GFile
321 *
322 * Checks whether @file is a non-removable local mount.
323 *
324 * Returns: %TRUE if @file is in a non-removable mount,
325 * %FALSE otherwise or when it is remote.
326 **/
327gboolean
328eoc_util_file_is_persistent (GFile *file)
329{
330 GMount *mount;
331
332 if (!g_file_is_native (file))
333 return FALSE(0);
334
335 mount = g_file_find_enclosing_mount (file, NULL((void*)0), NULL((void*)0));
336 if (mount) {
337 if (g_mount_can_unmount (mount)) {
338 return FALSE(0);
339 }
340 }
341
342 return TRUE(!(0));
343}
344
345static void
346_eoc_util_show_file_in_filemanager_fallback (GFile *file, CtkWindow *toplevel)
347{
348 gchar *uri = NULL((void*)0);
349 GError *error = NULL((void*)0);
350 guint32 timestamp = ctk_get_current_event_time ();
351
352 if (g_file_query_file_type (file, 0, NULL((void*)0)) == G_FILE_TYPE_DIRECTORY) {
353 uri = g_file_get_uri (file);
354 } else {
355 /* If input file is not a directory we must open it's
356 folder/parent to avoid opening the file itself */
357 GFile *parent_file;
358
359 parent_file = g_file_get_parent (file);
360 if (G_LIKELY (parent_file)(parent_file))
361 uri = g_file_get_uri (parent_file);
362 g_object_unref (parent_file);
363 }
364
365 if (uri && !ctk_show_uri_on_window (toplevel, uri, timestamp, &error)) {
366 g_warning ("Couldn't show containing folder \"%s\": %s", uri,
367 error->message);
368 g_error_free (error);
369 }
370
371 g_free (uri);
372}
373
374void
375eoc_util_show_file_in_filemanager (GFile *file, CtkWindow *toplevel)
376{
377 GDBusProxy *proxy;
378 gboolean done = FALSE(0);
379
380 g_return_if_fail (file != NULL)do { if ((file != ((void*)0))) { } else { g_return_if_fail_warning
("EOC", ((const char*) (__func__)), "file != NULL"); return;
} } while (0)
;
381
382 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
383 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
384 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
385 NULL((void*)0), "org.freedesktop.FileManager1",
386 "/org/freedesktop/FileManager1",
387 "org.freedesktop.FileManager1",
388 NULL((void*)0), NULL((void*)0));
389
390 if (proxy) {
391 gchar *uri = g_file_get_uri (file);
392 gchar *startup_id;
393 GVariant *params, *result;
394 GVariantBuilder builder;
395
396 g_variant_builder_init (&builder,
397 G_VARIANT_TYPE ("as")(g_variant_type_checked_ (("as"))));
398 g_variant_builder_add (&builder, "s", uri);
399
400 /* This seems to be the expected format, as other values
401 cause the filemanager window not to get focus. */
402 startup_id = g_strdup_printf("_TIME%u",
403 ctk_get_current_event_time());
404
405 /* params is floating! */
406 params = g_variant_new ("(ass)", &builder, startup_id);
407
408 g_free (startup_id);
409 g_variant_builder_clear (&builder);
410
411 /* Floating params-GVariant is consumed here */
412 result = g_dbus_proxy_call_sync (proxy, "ShowItems",
413 params, G_DBUS_CALL_FLAGS_NONE,
414 -1, NULL((void*)0), NULL((void*)0));
415
416 /* Receiving a non-NULL result counts as a successful call. */
417 if (G_LIKELY (result != NULL)(result != ((void*)0))) {
418 done = TRUE(!(0));
419 g_variant_unref (result);
420 }
421
422 g_free (uri);
423 g_object_unref (proxy);
424 }
425
426 /* Fallback to ctk_show_uri() if launch over DBus is not possible */
427 if (!done)
428 _eoc_util_show_file_in_filemanager_fallback (file, toplevel);
429}