Bug Summary

File:cafe-panel/libpanel-util/panel-launch.c
Warning:line 71, column 45
Access to field 'message' results in a dereference of a null pointer (loaded from variable 'local_error')

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 panel-launch.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/cafe-panel/libpanel-util -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -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/gdk-pixbuf-2.0 -I /usr/include/libpng16 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/ctk-3.0 -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/cafe-menus -I /usr/include/dconf -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 -I . -I . -I ../../cafe-panel/libpanel-util -D DATADIR="/usr/share" -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/cafe-panel/libpanel-util -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-121451-55967-1 -x c panel-launch.c
1/*
2 * panel-launch.c: some helpers to launch desktop files
3 *
4 * Copyright (C) 2008 Novell, Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301, USA.
20 *
21 * Authors:
22 * Vincent Untz <vuntz@gnome.org>
23 */
24
25#include <glib/gi18n.h>
26#include <gio/gio.h>
27#include <gio/gdesktopappinfo.h>
28
29#include <cdk/cdk.h>
30#include <ctk/ctk.h>
31
32#include "panel-error.h"
33#include "panel-glib.h"
34
35#include "panel-launch.h"
36
37static void
38_panel_launch_error_dialog (const gchar *name,
39 CdkScreen *screen,
40 const gchar *message)
41{
42 char *primary;
43
44 if (name)
45 primary = g_markup_printf_escaped (_("Could not launch '%s'")gettext ("Could not launch '%s'"),
46 name);
47 else
48 primary = g_strdup (_("Could not launch application"))g_strdup_inline (gettext ("Could not launch application"));
49
50 panel_error_dialog (NULL((void*)0), screen, "cannot_launch", TRUE(!(0)),
51 primary, message);
52 g_free (primary);
53}
54
55static gboolean
56_panel_launch_handle_error (const gchar *name,
57 CdkScreen *screen,
58 GError *local_error,
59 GError **error)
60{
61 if (g_error_matches (local_error,
33
Assuming the condition is false
34
Taking false branch
62 G_IO_ERRORg_io_error_quark(), G_IO_ERROR_CANCELLED)) {
63 g_error_free (local_error);
64 return TRUE(!(0));
65 }
66
67 else if (error
34.1
'error' is equal to NULL
!= NULL((void*)0))
35
Taking false branch
68 g_propagate_error (error, local_error);
69
70 else {
71 _panel_launch_error_dialog (name, screen, local_error->message);
36
Access to field 'message' results in a dereference of a null pointer (loaded from variable 'local_error')
72 g_error_free (local_error);
73 }
74
75 return FALSE(0);
76}
77
78static void
79dummy_child_watch (GPid pid,
80 gint status,
81 gpointer user_data)
82{
83 /* Nothing, this is just to ensure we don't double fork
84 * and break pkexec:
85 * https://bugzilla.gnome.org/show_bug.cgi?id=675789
86 */
87}
88
89static void
90gather_pid_callback (GDesktopAppInfo *gapp,
91 GPid pid,
92 gpointer data)
93{
94 g_child_watch_add (pid, dummy_child_watch, NULL((void*)0));
95}
96
97gboolean
98panel_app_info_launch_uris (GDesktopAppInfo *appinfo,
99 GList *uris,
100 CdkScreen *screen,
101 const gchar *action,
102 guint32 timestamp,
103 GError **error)
104{
105 CdkAppLaunchContext *context;
106 GError *local_error;
107 gboolean retval;
108
109 g_return_val_if_fail (G_IS_DESKTOP_APP_INFO (appinfo), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((appinfo)); GType __t = ((g_desktop_app_info_get_type ())
); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; })))))) { } else { g_return_if_fail_warning (((gchar*) 0
), ((const char*) (__func__)), "G_IS_DESKTOP_APP_INFO (appinfo)"
); return ((0)); } } while (0)
;
15
Taking false branch
16
Assuming field 'g_class' is null
17
Assuming the condition is true
18
Taking true branch
19
Loop condition is false. Exiting loop
110 g_return_val_if_fail (CDK_IS_SCREEN (screen), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((cdk_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "CDK_IS_SCREEN (screen)"); return ((0)); } } while
(0)
;
20
Taking false branch
21
Assuming the condition is true
22
Taking true branch
111 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "error == NULL || *error == NULL"); return ((0)); } } while
(0)
;
23
Loop condition is false. Exiting loop
24
Loop condition is false. Exiting loop
112
113 CdkDisplay *display = cdk_display_get_default ();
114 context = cdk_display_get_app_launch_context (display);
115 cdk_app_launch_context_set_screen (context, screen);
116 cdk_app_launch_context_set_timestamp (context, timestamp);
117
118 local_error = NULL((void*)0);
119 if (action == NULL((void*)0)) {
25
Assuming 'action' is equal to NULL
26
Taking true branch
120 retval = g_desktop_app_info_launch_uris_as_manager (appinfo, uris,
27
Value assigned to 'local_error'
121 G_APP_LAUNCH_CONTEXT (context)((((GAppLaunchContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((g_app_launch_context_get_type
()))))))
,
122 G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
123 NULL((void*)0), NULL((void*)0), gather_pid_callback, appinfo,
124 &local_error);
125 } else {
126 g_desktop_app_info_launch_action (appinfo, action, G_APP_LAUNCH_CONTEXT (context)((((GAppLaunchContext*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((context)), ((g_app_launch_context_get_type
()))))))
);
127 retval = TRUE(!(0));
128 }
129
130 g_object_unref (context);
131
132 if ((local_error == NULL((void*)0)) && (retval == TRUE(!(0))))
28
Assuming 'local_error' is equal to NULL
29
Assuming the condition is false
30
Taking false branch
133 return TRUE(!(0));
134
135 return _panel_launch_handle_error (g_app_info_get_name (G_APP_INFO(appinfo)((((GAppInfo*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((appinfo)), ((g_app_info_get_type ()))))))
),
32
Calling '_panel_launch_handle_error'
136 screen, local_error, error);
31
Passing null pointer value via 3rd parameter 'local_error'
137}
138
139gboolean
140panel_app_info_launch_uri (GDesktopAppInfo *appinfo,
141 const gchar *uri,
142 CdkScreen *screen,
143 guint32 timestamp,
144 GError **error)
145{
146 GList *uris;
147 gboolean retval;
148
149 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((appinfo)); GType __t = ((g_app_info_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "G_IS_APP_INFO (appinfo)"); return ((0)); } } while
(0)
;
150 g_return_val_if_fail (CDK_IS_SCREEN (screen), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((cdk_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "CDK_IS_SCREEN (screen)"); return ((0)); } } while
(0)
;
151 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "error == NULL || *error == NULL"); return ((0)); } } while
(0)
;
152
153 uris = NULL((void*)0);
154 if (uri)
155 uris = g_list_prepend (uris, (gpointer) uri);
156
157 retval = panel_app_info_launch_uris (appinfo, uris,
158 screen, NULL((void*)0), timestamp, error);
159
160 g_list_free (uris);
161
162 return retval;
163}
164
165gboolean
166panel_launch_key_file (GKeyFile *keyfile,
167 GList *uri_list,
168 CdkScreen *screen,
169 const gchar *action,
170 GError **error)
171{
172 GDesktopAppInfo *appinfo;
173 gboolean retval;
174
175 g_return_val_if_fail (keyfile != NULL, FALSE)do { if ((keyfile != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "keyfile != NULL"
); return ((0)); } } while (0)
;
1
Assuming 'keyfile' is not equal to null
2
Taking true branch
3
Loop condition is false. Exiting loop
176 g_return_val_if_fail (CDK_IS_SCREEN (screen), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((cdk_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "CDK_IS_SCREEN (screen)"); return ((0)); } } while
(0)
;
4
Assuming '__inst' is non-null
5
Taking false branch
6
Assuming field 'g_class' is null
7
Assuming the condition is true
8
Taking true branch
177 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "error == NULL || *error == NULL"); return ((0)); } } while
(0)
;
9
Loop condition is false. Exiting loop
10
Assuming 'error' is equal to null
11
Loop condition is false. Exiting loop
178
179 appinfo = g_desktop_app_info_new_from_keyfile (keyfile);
180 if (appinfo == NULL((void*)0))
12
Assuming 'appinfo' is not equal to NULL
13
Taking false branch
181 return FALSE(0);
182
183 retval = panel_app_info_launch_uris (appinfo,
14
Calling 'panel_app_info_launch_uris'
184 uri_list, screen, action,
185 ctk_get_current_event_time (),
186 error);
187
188 g_object_unref (appinfo);
189 return retval;
190}
191
192gboolean
193panel_launch_desktop_file (const char *desktop_file,
194 CdkScreen *screen,
195 GError **error)
196{
197 GDesktopAppInfo *appinfo;
198 gboolean retval;
199
200 g_return_val_if_fail (desktop_file != NULL, FALSE)do { if ((desktop_file != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "desktop_file != NULL"
); return ((0)); } } while (0)
;
201 g_return_val_if_fail (CDK_IS_SCREEN (screen), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((cdk_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "CDK_IS_SCREEN (screen)"); return ((0)); } } while
(0)
;
202 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "error == NULL || *error == NULL"); return ((0)); } } while
(0)
;
203
204 appinfo = NULL((void*)0);
205
206 if (g_path_is_absolute (desktop_file))
207 appinfo = g_desktop_app_info_new_from_filename (desktop_file);
208 else {
209 char *full;
210
211 full = panel_g_lookup_in_applications_dirs (desktop_file);
212 if (full) {
213 appinfo = g_desktop_app_info_new_from_filename (full);
214 g_free (full);
215 }
216 }
217
218 if (appinfo == NULL((void*)0))
219 return FALSE(0);
220
221 retval = panel_app_info_launch_uris (appinfo, NULL((void*)0), screen, NULL((void*)0),
222 ctk_get_current_event_time (),
223 error);
224
225 g_object_unref (appinfo);
226
227 return retval;
228}
229
230/*
231 * Set the DISPLAY variable, to be use by g_spawn_async.
232 */
233static void
234set_environment (gpointer display)
235{
236 g_setenv ("DISPLAY", display, TRUE(!(0)));
237}
238
239gboolean
240panel_launch_desktop_file_with_fallback (const char *desktop_file,
241 const char *fallback_exec,
242 CdkScreen *screen,
243 GError **error)
244{
245 char *argv[2] = { (char *) fallback_exec, NULL((void*)0) };
246 GError *local_error;
247 gboolean retval;
248 GPid pid;
249 CdkDisplay *display;
250 char *display_name;
251
252 g_return_val_if_fail (desktop_file != NULL, FALSE)do { if ((desktop_file != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "desktop_file != NULL"
); return ((0)); } } while (0)
;
253 g_return_val_if_fail (fallback_exec != NULL, FALSE)do { if ((fallback_exec != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "fallback_exec != NULL"
); return ((0)); } } while (0)
;
254 g_return_val_if_fail (CDK_IS_SCREEN (screen), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((screen)); GType __t = ((cdk_screen_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "CDK_IS_SCREEN (screen)"); return ((0)); } } while
(0)
;
255 g_return_val_if_fail (error == NULL || *error == NULL, FALSE)do { if ((error == ((void*)0) || *error == ((void*)0))) { } else
{ g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "error == NULL || *error == NULL"); return ((0)); } } while
(0)
;
256
257 /* need to pass a non-NULL error to avoid getting a dialog */
258 local_error = NULL((void*)0);
259 if (panel_launch_desktop_file (desktop_file, screen, &local_error))
260 return TRUE(!(0));
261
262 if (local_error) {
263 g_error_free (local_error);
264 local_error = NULL((void*)0);
265 }
266
267 display = cdk_screen_get_display (screen);
268 display_name = g_strdup (cdk_display_get_name (display))g_strdup_inline (cdk_display_get_name (display));
269 retval = g_spawn_async (NULL((void*)0), /* working directory */
270 argv,
271 NULL((void*)0), /* envp */
272 G_SPAWN_SEARCH_PATH,
273 set_environment,
274 &display_name,
275 &pid,
276 &local_error);
277 g_free (display_name);
278
279 if (local_error == NULL((void*)0) && retval == TRUE(!(0))) {
280 g_child_watch_add (pid, dummy_child_watch, NULL((void*)0));
281 }
282 return TRUE(!(0));
283
284 return _panel_launch_handle_error (fallback_exec,
285 screen, local_error, error);
286}