Bug Summary

File:plugins/xsettings/xsettings-manager.c
Warning:line 327, column 20
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 xsettings-manager.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/plugins/xsettings -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -I ../../cafe-settings-daemon -D CAFE_SETTINGS_LOCALEDIR="/usr/share/locale" -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/freetype2 -I /usr/include/libpng16 -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/plugins/xsettings -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-21-030324-65499-1 -x c xsettings-manager.c
1/*
2 * Copyright © 2001 Red Hat, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Red Hat not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. Red Hat makes no representations about the
11 * suitability of this software for any purpose. It is provided "as is"
12 * without express or implied warranty.
13 *
14 * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
16 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
18 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
19 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 * Author: Owen Taylor, Red Hat, Inc.
22 */
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include <X11/Xmd.h> /* For CARD16 */
28
29#include "xsettings-manager.h"
30
31struct _XSettingsManager
32{
33 Display *display;
34 int screen;
35
36 Window window;
37 Atom manager_atom;
38 Atom selection_atom;
39 Atom xsettings_atom;
40
41 XSettingsTerminateFunc terminate;
42 void *cb_data;
43
44 XSettingsList *settings;
45 unsigned long serial;
46};
47
48static XSettingsList *settings;
49
50typedef struct
51{
52 Window window;
53 Atom timestamp_prop_atom;
54} TimeStampInfo;
55
56static Boolint
57timestamp_predicate (Display *display,
58 XEvent *xevent,
59 XPointer arg)
60{
61 TimeStampInfo *info = (TimeStampInfo *)arg;
62
63 if (xevent->type == PropertyNotify28 &&
64 xevent->xproperty.window == info->window &&
65 xevent->xproperty.atom == info->timestamp_prop_atom)
66 return True1;
67
68 return False0;
69}
70
71/**
72 * get_server_time:
73 * @display: display from which to get the time
74 * @window: a #Window, used for communication with the server.
75 * The window must have PropertyChangeMask in its
76 * events mask or a hang will result.
77 *
78 * Routine to get the current X server time stamp.
79 *
80 * Return value: the time stamp.
81 **/
82static Time
83get_server_time (Display *display,
84 Window window)
85{
86 unsigned char c = 'a';
87 XEvent xevent;
88 TimeStampInfo info;
89
90 info.timestamp_prop_atom = XInternAtom (display, "_TIMESTAMP_PROP", False0);
91 info.window = window;
92
93 XChangeProperty (display, window,
94 info.timestamp_prop_atom, info.timestamp_prop_atom,
95 8, PropModeReplace0, &c, 1);
96
97 XIfEvent (display, &xevent,
98 timestamp_predicate, (XPointer)&info);
99
100 return xevent.xproperty.time;
101}
102
103Boolint
104xsettings_manager_check_running (Display *display,
105 int screen)
106{
107 char buffer[256];
108 Atom selection_atom;
109
110 sprintf(buffer, "_XSETTINGS_S%d", screen);
111 selection_atom = XInternAtom (display, buffer, False0);
112
113 if (XGetSelectionOwner (display, selection_atom))
114 return True1;
115 else
116 return False0;
117}
118
119XSettingsManager *
120xsettings_manager_new (Display *display,
121 int screen,
122 XSettingsTerminateFunc terminate,
123 void *cb_data)
124{
125 XSettingsManager *manager;
126 Time timestamp;
127 XClientMessageEvent xev;
128
129 char buffer[256];
130
131 manager = malloc (sizeof *manager);
132 if (!manager)
133 return NULL((void*)0);
134
135 manager->display = display;
136 manager->screen = screen;
137
138 sprintf(buffer, "_XSETTINGS_S%d", screen);
139 manager->selection_atom = XInternAtom (display, buffer, False0);
140 manager->xsettings_atom = XInternAtom (display, "_XSETTINGS_SETTINGS", False0);
141 manager->manager_atom = XInternAtom (display, "MANAGER", False0);
142
143 manager->terminate = terminate;
144 manager->cb_data = cb_data;
145
146 manager->settings = NULL((void*)0);
147 manager->serial = 0;
148
149 manager->window = XCreateSimpleWindow (display,
150 RootWindow (display, screen)((&((_XPrivDisplay)(display))->screens[screen])->root
)
,
151 0, 0, 10, 10, 0,
152 WhitePixel (display, screen)((&((_XPrivDisplay)(display))->screens[screen])->white_pixel
)
,
153 WhitePixel (display, screen)((&((_XPrivDisplay)(display))->screens[screen])->white_pixel
)
);
154
155 XSelectInput (display, manager->window, PropertyChangeMask(1L<<22));
156 timestamp = get_server_time (display, manager->window);
157
158 XSetSelectionOwner (display, manager->selection_atom,
159 manager->window, timestamp);
160
161 /* Check to see if we managed to claim the selection. If not,
162 * we treat it as if we got it then immediately lost it
163 */
164
165 if (XGetSelectionOwner (display, manager->selection_atom) ==
166 manager->window)
167 {
168 xev.type = ClientMessage33;
169 xev.window = RootWindow (display, screen)((&((_XPrivDisplay)(display))->screens[screen])->root
)
;
170 xev.message_type = manager->manager_atom;
171 xev.format = 32;
172 xev.data.l[0] = timestamp;
173 xev.data.l[1] = manager->selection_atom;
174 xev.data.l[2] = manager->window;
175 xev.data.l[3] = 0; /* manager specific data */
176 xev.data.l[4] = 0; /* manager specific data */
177
178 XSendEvent (display, RootWindow (display, screen)((&((_XPrivDisplay)(display))->screens[screen])->root
)
,
179 False0, StructureNotifyMask(1L<<17), (XEvent *)&xev);
180 }
181 else
182 {
183 manager->terminate (manager->cb_data);
184 }
185
186 return manager;
187}
188
189void
190xsettings_manager_destroy (XSettingsManager *manager)
191{
192 XDestroyWindow (manager->display, manager->window);
193
194 xsettings_list_free (manager->settings);
195 free (manager);
196}
197
198Window
199xsettings_manager_get_window (XSettingsManager *manager)
200{
201 return manager->window;
202}
203
204Boolint
205xsettings_manager_process_event (XSettingsManager *manager,
206 XEvent *xev)
207{
208 if (xev->xany.window == manager->window &&
209 xev->xany.type == SelectionClear29 &&
210 xev->xselectionclear.selection == manager->selection_atom)
211 {
212 manager->terminate (manager->cb_data);
213 return True1;
214 }
215
216 return False0;
217}
218
219XSettingsResult
220xsettings_manager_delete_setting (XSettingsManager *manager,
221 const char *name)
222{
223 return xsettings_list_delete (&settings, name);
224}
225
226XSettingsResult
227xsettings_manager_set_setting (XSettingsManager *manager,
228 XSettingsSetting *setting)
229{
230 XSettingsSetting *old_setting = xsettings_list_lookup (settings, setting->name);
231 XSettingsSetting *new_setting;
232 XSettingsResult result;
233
234 if (old_setting)
235 {
236 if (xsettings_setting_equal (old_setting, setting))
237 return XSETTINGS_SUCCESS;
238
239 xsettings_list_delete (&settings, setting->name);
240 }
241
242 new_setting = xsettings_setting_copy (setting);
243 if (!new_setting)
244 return XSETTINGS_NO_MEM;
245
246 new_setting->last_change_serial = manager->serial;
247
248 result = xsettings_list_insert (&settings, new_setting);
249
250 if (result != XSETTINGS_SUCCESS)
251 xsettings_setting_free (new_setting);
252
253 return result;
254}
255
256XSettingsResult
257xsettings_manager_set_int (XSettingsManager *manager,
258 const char *name,
259 int value)
260{
261 XSettingsSetting setting;
262
263 setting.name = (char *)name;
264 setting.type = XSETTINGS_TYPE_INT;
265 setting.data.v_int = value;
266
267 return xsettings_manager_set_setting (manager, &setting);
268}
269
270XSettingsResult
271xsettings_manager_set_string (XSettingsManager *manager,
272 const char *name,
273 const char *value)
274{
275 XSettingsSetting setting;
276
277 setting.name = (char *)name;
278 setting.type = XSETTINGS_TYPE_STRING;
279 setting.data.v_string = (char *)value;
280
281 return xsettings_manager_set_setting (manager, &setting);
282}
283
284XSettingsResult
285xsettings_manager_set_color (XSettingsManager *manager,
286 const char *name,
287 XSettingsColor *value)
288{
289 XSettingsSetting setting;
290
291 setting.name = (char *)name;
292 setting.type = XSETTINGS_TYPE_COLOR;
293 setting.data.v_color = *value;
294
295 return xsettings_manager_set_setting (manager, &setting);
296}
297
298static size_t
299setting_length (XSettingsSetting *setting)
300{
301 size_t length = 8; /* type + pad + name-len + last-change-serial */
302 length += XSETTINGS_PAD (strlen (setting->name), 4)((strlen (setting->name) + 4 - 1) & (~(4 -1)));
303
304 switch (setting->type)
305 {
306 case XSETTINGS_TYPE_INT:
307 length += 4;
308 break;
309 case XSETTINGS_TYPE_STRING:
310 length += 4 + XSETTINGS_PAD (strlen (setting->data.v_string), 4)((strlen (setting->data.v_string) + 4 - 1) & (~(4 -1))
)
;
311 break;
312 case XSETTINGS_TYPE_COLOR:
313 length += 8;
314 break;
315 }
316
317 return length;
318}
319
320static void
321setting_store (XSettingsSetting *setting,
322 XSettingsBuffer *buffer)
323{
324 size_t string_len;
325 size_t length;
326
327 *(buffer->pos++) = setting->type;
6
Out of bound memory access (access exceeds upper limit of memory block)
328 *(buffer->pos++) = 0;
329
330 string_len = strlen (setting->name);
331 *(CARD16 *)(buffer->pos) = string_len;
332 buffer->pos += 2;
333
334 length = XSETTINGS_PAD (string_len, 4)((string_len + 4 - 1) & (~(4 -1)));
335 memcpy (buffer->pos, setting->name, string_len);
336 length -= string_len;
337 buffer->pos += string_len;
338
339 while (length > 0)
340 {
341 *(buffer->pos++) = 0;
342 length--;
343 }
344
345 *(CARD32 *)(buffer->pos) = setting->last_change_serial;
346 buffer->pos += 4;
347
348 switch (setting->type)
349 {
350 case XSETTINGS_TYPE_INT:
351 *(CARD32 *)(buffer->pos) = setting->data.v_int;
352 buffer->pos += 4;
353 break;
354 case XSETTINGS_TYPE_STRING:
355 string_len = strlen (setting->data.v_string);
356 *(CARD32 *)(buffer->pos) = string_len;
357 buffer->pos += 4;
358
359 length = XSETTINGS_PAD (string_len, 4)((string_len + 4 - 1) & (~(4 -1)));
360 memcpy (buffer->pos, setting->data.v_string, string_len);
361 length -= string_len;
362 buffer->pos += string_len;
363
364 while (length > 0)
365 {
366 *(buffer->pos++) = 0;
367 length--;
368 }
369 break;
370 case XSETTINGS_TYPE_COLOR:
371 *(CARD16 *)(buffer->pos) = setting->data.v_color.red;
372 *(CARD16 *)(buffer->pos + 2) = setting->data.v_color.green;
373 *(CARD16 *)(buffer->pos + 4) = setting->data.v_color.blue;
374 *(CARD16 *)(buffer->pos + 6) = setting->data.v_color.alpha;
375 buffer->pos += 8;
376 break;
377 }
378}
379
380XSettingsResult
381xsettings_manager_notify (XSettingsManager *manager)
382{
383 XSettingsBuffer buffer;
384 XSettingsList *iter;
385 int n_settings = 0;
386
387 buffer.len = 12; /* byte-order + pad + SERIAL + N_SETTINGS */
388
389 iter = settings;
390 while (iter)
1
Loop condition is false. Execution continues on line 397
391 {
392 buffer.len += setting_length (iter->setting);
393 n_settings++;
394 iter = iter->next;
395 }
396
397 buffer.data = buffer.pos = malloc (buffer.len);
398 if (!buffer.data)
2
Assuming field 'data' is non-null
3
Taking false branch
399 return XSETTINGS_NO_MEM;
400
401 *buffer.pos = xsettings_byte_order ();
402
403 buffer.pos += 4;
404 *(CARD32 *)buffer.pos = manager->serial++;
405 buffer.pos += 4;
406 *(CARD32 *)buffer.pos = n_settings;
407 buffer.pos += 4;
408
409 iter = settings;
410 while (iter)
4
Loop condition is true. Entering loop body
411 {
412 setting_store (iter->setting, &buffer);
5
Calling 'setting_store'
413 iter = iter->next;
414 }
415
416 XChangeProperty (manager->display, manager->window,
417 manager->xsettings_atom, manager->xsettings_atom,
418 8, PropModeReplace0, buffer.data, buffer.len);
419
420 free (buffer.data);
421
422 return XSETTINGS_SUCCESS;
423}
424