Bug Summary

File:ctk/ctkallocatedbitmask.c
Warning:line 313, column 19
Out of bound memory access (accessed memory precedes 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 ctkallocatedbitmask.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/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -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/sysprof-6 -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/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -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/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -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/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -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/14/../../../../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/ctk -ferror-limit 19 -fvisibility=hidden -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-09-19-172619-43637-1 -x c ctkallocatedbitmask.c
1/*
2 * Copyright © 2011 Red Hat Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library 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 GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authors: Benjamin Otte <otte@gnome.org>
18 */
19
20#include <config.h>
21
22#include "ctkallocatedbitmaskprivate.h"
23#include "ctkprivate.h"
24
25
26#define VALUE_TYPEgsize gsize
27
28#define VALUE_SIZE_BITS(sizeof (gsize) * 8) (sizeof (VALUE_TYPEgsize) * 8)
29#define VALUE_BIT(idx)(((gsize) 1) << (idx)) (((VALUE_TYPEgsize) 1) << (idx))
30#define ALL_BITS(~((gsize) 0)) (~((VALUE_TYPEgsize) 0))
31
32struct _CtkBitmask {
33 gsize len;
34 VALUE_TYPEgsize data[1];
35};
36
37#define ENSURE_ALLOCATED(mask, heap_mask)do { if (!(!(((gsize) (mask)) & 1))) { heap_mask.data[0] =
(((gsize) (mask)) >> ((gsize) 1)); heap_mask.len = heap_mask
.data[0] ? 1 : 0; mask = &heap_mask; } } while (0)
G_STMT_STARTdo { \
38 if (!_ctk_bitmask_is_allocated (mask)(!(((gsize) (mask)) & 1))) \
39 { \
40 heap_mask.data[0] = _ctk_bitmask_to_bits (mask)(((gsize) (mask)) >> ((gsize) 1)); \
41 heap_mask.len = heap_mask.data[0] ? 1 : 0; \
42 mask = &heap_mask; \
43 } \
44} G_STMT_ENDwhile (0)
45
46static CtkBitmask *
47ctk_allocated_bitmask_resize (CtkBitmask *mask,
48 gsize size) G_GNUC_WARN_UNUSED_RESULT__attribute__((warn_unused_result));
49static CtkBitmask *
50ctk_allocated_bitmask_resize (CtkBitmask *mask,
51 gsize size)
52{
53 gsize i;
54
55 if (size == mask->len)
56 return mask;
57
58 mask = g_realloc (mask, sizeof (CtkBitmask) + sizeof(VALUE_TYPEgsize) * (size - 1));
59
60 for (i = mask->len; i < size; i++)
61 mask->data[i] = 0;
62
63 mask->len = size;
64
65 return mask;
66}
67
68static CtkBitmask *
69ctk_allocated_bitmask_new_for_bits (gsize bits)
70{
71 CtkBitmask *mask;
72
73 mask = g_malloc (sizeof (CtkBitmask));
74 mask->len = bits ? 1 : 0;
75 mask->data[0] = bits;
76
77 return mask;
78}
79
80static CtkBitmask *
81ctk_bitmask_ensure_allocated (CtkBitmask *mask)
82{
83 if (_ctk_bitmask_is_allocated (mask)(!(((gsize) (mask)) & 1)))
84 return mask;
85 else
86 return ctk_allocated_bitmask_new_for_bits (_ctk_bitmask_to_bits (mask)(((gsize) (mask)) >> ((gsize) 1)));
87}
88
89CtkBitmask *
90_ctk_allocated_bitmask_copy (const CtkBitmask *mask)
91{
92 CtkBitmask *copy;
93
94 ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return
(((void*)0)); } } while (0)
;
95
96 copy = ctk_allocated_bitmask_new_for_bits (0);
97
98 return _ctk_allocated_bitmask_union (copy, mask);
99}
100
101void
102_ctk_allocated_bitmask_free (CtkBitmask *mask)
103{
104 ctk_internal_return_if_fail (mask != NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return
; } } while (0)
;
105
106 g_free (mask);
107}
108
109void
110_ctk_allocated_bitmask_print (const CtkBitmask *mask,
111 GString *string)
112{
113 CtkBitmask mask_allocated;
114 int i;
115
116 ctk_internal_return_if_fail (mask != NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return
; } } while (0)
;
117 ctk_internal_return_if_fail (string != NULL)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "string != ((void*)0)");
return; } } while (0)
;
118
119 ENSURE_ALLOCATED (mask, mask_allocated)do { if (!(!(((gsize) (mask)) & 1))) { mask_allocated.data
[0] = (((gsize) (mask)) >> ((gsize) 1)); mask_allocated
.len = mask_allocated.data[0] ? 1 : 0; mask = &mask_allocated
; } } while (0)
;
120
121 for (i = mask->len * VALUE_SIZE_BITS(sizeof (gsize) * 8) - 1; i >= 0; i--)
122 {
123 if (_ctk_allocated_bitmask_get (mask, i))
124 break;
125 }
126
127 if (i < 0)
128 {
129 g_string_append_c (string, '0')g_string_append_c_inline (string, '0');
130 return;
131 }
132
133 for (; i >= 0; i--)
134 {
135 g_string_append_c (string, _ctk_allocated_bitmask_get (mask, i) ? '1' : '0')g_string_append_c_inline (string, _ctk_allocated_bitmask_get (
mask, i) ? '1' : '0')
;
136 }
137}
138
139/* NB: Call this function whenever the
140 * array might have become too large.
141 * _ctk_allocated_bitmask_is_empty() depends on this.
142 */
143static CtkBitmask *
144ctk_allocated_bitmask_shrink (CtkBitmask *mask) G_GNUC_WARN_UNUSED_RESULT__attribute__((warn_unused_result));
145static CtkBitmask *
146ctk_allocated_bitmask_shrink (CtkBitmask *mask)
147{
148 guint i;
149
150 for (i = mask->len; i; i--)
151 {
152 if (mask->data[i - 1])
153 break;
154 }
155
156 if (i == 0 ||
157 (i == 1 && mask->data[0] < VALUE_BIT (CTK_BITMASK_N_DIRECT_BITS)(((gsize) 1) << ((sizeof (gsize) * 8 - 1)))))
158 {
159 CtkBitmask *result = _ctk_bitmask_from_bits (i == 0 ? 0 : mask->data[0])((gpointer) (guintptr) (gsize) ((((gsize) (i == 0 ? 0 : mask->
data[0])) << 1) | 1))
;
160 _ctk_allocated_bitmask_free (mask);
161 return result;
162 }
163
164 return ctk_allocated_bitmask_resize (mask, i);
165}
166
167CtkBitmask *
168_ctk_allocated_bitmask_intersect (CtkBitmask *mask,
169 const CtkBitmask *other)
170{
171 CtkBitmask other_allocated;
172 guint i;
173
174 ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return
(((void*)0)); } } while (0)
;
175 ctk_internal_return_val_if_fail (other != NULL, NULL)do { if ((other != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "other != ((void*)0)"); return
(((void*)0)); } } while (0)
;
176
177 mask = ctk_bitmask_ensure_allocated (mask);
178 ENSURE_ALLOCATED (other, other_allocated)do { if (!(!(((gsize) (other)) & 1))) { other_allocated.data
[0] = (((gsize) (other)) >> ((gsize) 1)); other_allocated
.len = other_allocated.data[0] ? 1 : 0; other = &other_allocated
; } } while (0)
;
179
180 for (i = 0; i < MIN (mask->len, other->len)(((mask->len) < (other->len)) ? (mask->len) : (other
->len))
; i++)
181 {
182 mask->data[i] &= other->data[i];
183 }
184 for (; i < mask->len; i++)
185 {
186 mask->data[i] = 0;
187 }
188
189 return ctk_allocated_bitmask_shrink (mask);
190}
191
192CtkBitmask *
193_ctk_allocated_bitmask_union (CtkBitmask *mask,
194 const CtkBitmask *other)
195{
196 CtkBitmask other_allocated;
197 guint i;
198
199 ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return
(((void*)0)); } } while (0)
;
200 ctk_internal_return_val_if_fail (other != NULL, NULL)do { if ((other != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "other != ((void*)0)"); return
(((void*)0)); } } while (0)
;
201
202 mask = ctk_bitmask_ensure_allocated (mask);
203 ENSURE_ALLOCATED (other, other_allocated)do { if (!(!(((gsize) (other)) & 1))) { other_allocated.data
[0] = (((gsize) (other)) >> ((gsize) 1)); other_allocated
.len = other_allocated.data[0] ? 1 : 0; other = &other_allocated
; } } while (0)
;
204
205 mask = ctk_allocated_bitmask_resize (mask, MAX (mask->len, other->len)(((mask->len) > (other->len)) ? (mask->len) : (other
->len))
);
206 for (i = 0; i < other->len; i++)
207 {
208 mask->data[i] |= other->data[i];
209 }
210
211 return mask;
212}
213
214CtkBitmask *
215_ctk_allocated_bitmask_subtract (CtkBitmask *mask,
216 const CtkBitmask *other)
217{
218 CtkBitmask other_allocated;
219 guint i, len;
220
221 ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return
(((void*)0)); } } while (0)
;
222 ctk_internal_return_val_if_fail (other != NULL, NULL)do { if ((other != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "other != ((void*)0)"); return
(((void*)0)); } } while (0)
;
223
224 mask = ctk_bitmask_ensure_allocated (mask);
225 ENSURE_ALLOCATED (other, other_allocated)do { if (!(!(((gsize) (other)) & 1))) { other_allocated.data
[0] = (((gsize) (other)) >> ((gsize) 1)); other_allocated
.len = other_allocated.data[0] ? 1 : 0; other = &other_allocated
; } } while (0)
;
226
227 len = MIN (mask->len, other->len)(((mask->len) < (other->len)) ? (mask->len) : (other
->len))
;
228 for (i = 0; i < len; i++)
229 {
230 mask->data[i] &= ~other->data[i];
231 }
232
233 return ctk_allocated_bitmask_shrink (mask);
234}
235
236static inline void
237ctk_allocated_bitmask_indexes (guint index_,
238 guint *array_index,
239 guint *bit_index)
240{
241 *array_index = index_ / VALUE_SIZE_BITS(sizeof (gsize) * 8);
242 *bit_index = index_ % VALUE_SIZE_BITS(sizeof (gsize) * 8);
243}
244
245gboolean
246_ctk_allocated_bitmask_get (const CtkBitmask *mask,
247 guint index_)
248{
249 guint array_index, bit_index;
250
251 ctk_internal_return_val_if_fail (mask != NULL, FALSE)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return
((0)); } } while (0)
;
252
253 ctk_allocated_bitmask_indexes (index_, &array_index, &bit_index);
254
255 if (array_index >= mask->len)
256 return FALSE(0);
257
258 return (mask->data[array_index] & VALUE_BIT (bit_index)(((gsize) 1) << (bit_index))) ? TRUE(!(0)) : FALSE(0);
259}
260
261CtkBitmask *
262_ctk_allocated_bitmask_set (CtkBitmask *mask,
263 guint index_,
264 gboolean value)
265{
266 guint array_index, bit_index;
267
268 ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return
(((void*)0)); } } while (0)
;
269
270 mask = ctk_bitmask_ensure_allocated (mask);
271 ctk_allocated_bitmask_indexes (index_, &array_index, &bit_index);
272
273 if (value)
274 {
275 if (array_index >= mask->len)
276 mask = ctk_allocated_bitmask_resize (mask, array_index + 1);
277
278 mask->data[array_index] |= VALUE_BIT (bit_index)(((gsize) 1) << (bit_index));
279 }
280 else
281 {
282 if (array_index < mask->len)
283 {
284 mask->data[array_index] &= ~ VALUE_BIT (bit_index)(((gsize) 1) << (bit_index));
285 mask = ctk_allocated_bitmask_shrink (mask);
286 }
287 }
288
289 return mask;
290}
291
292CtkBitmask *
293_ctk_allocated_bitmask_invert_range (CtkBitmask *mask,
294 guint start,
295 guint end)
296{
297 guint i;
298 guint start_word, start_bit;
299 guint end_word, end_bit;
300
301 ctk_internal_return_val_if_fail (mask != NULL, NULL)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return
(((void*)0)); } } while (0)
;
1
Assuming 'mask' is not equal to null
2
Taking true branch
3
Loop condition is false. Exiting loop
302 ctk_internal_return_val_if_fail (start < end, NULL)do { if ((start < end)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "start < end"); return
(((void*)0)); } } while (0)
;
4
Assuming 'start' is < 'end'
5
Taking true branch
6
Loop condition is false. Exiting loop
303
304 mask = ctk_bitmask_ensure_allocated (mask);
305
306 ctk_allocated_bitmask_indexes (start, &start_word, &start_bit);
307 ctk_allocated_bitmask_indexes (end - 1, &end_word, &end_bit);
308
309 if (end_word >= mask->len)
7
Assuming 'end_word' is >= field 'len'
8
Taking true branch
310 mask = ctk_allocated_bitmask_resize (mask, end_word + 1);
311
312 for (i = start_word; i
10.1
'i' is <= 'end_word'
<= end_word
; i++)
9
Assuming 'i' is <= 'end_word'
10
Loop condition is true. Entering loop body
11
Loop condition is true. Entering loop body
313 mask->data[i] ^= ALL_BITS(~((gsize) 0));
12
Out of bound memory access (accessed memory precedes memory block)
314 mask->data[start_word] ^= (((VALUE_TYPEgsize) 1) << start_bit) - 1;
315 if (end_bit != VALUE_SIZE_BITS(sizeof (gsize) * 8) - 1)
316 mask->data[end_word] ^= ALL_BITS(~((gsize) 0)) << (end_bit + 1);
317
318 return ctk_allocated_bitmask_shrink (mask);
319}
320
321gboolean
322_ctk_allocated_bitmask_equals (const CtkBitmask *mask,
323 const CtkBitmask *other)
324{
325 guint i;
326
327 ctk_internal_return_val_if_fail (mask != NULL, FALSE)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return
((0)); } } while (0)
;
328 ctk_internal_return_val_if_fail (other != NULL, FALSE)do { if ((other != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "other != ((void*)0)"); return
((0)); } } while (0)
;
329
330 if (mask->len != other->len)
331 return FALSE(0);
332
333 for (i = 0; i < mask->len; i++)
334 {
335 if (mask->data[i] != other->data[i])
336 return FALSE(0);
337 }
338
339 return TRUE(!(0));
340}
341
342gboolean
343_ctk_allocated_bitmask_intersects (const CtkBitmask *mask,
344 const CtkBitmask *other)
345{
346 CtkBitmask mask_allocated, other_allocated;
347 int i;
348
349 ctk_internal_return_val_if_fail (mask != NULL, FALSE)do { if ((mask != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mask != ((void*)0)"); return
((0)); } } while (0)
;
350 ctk_internal_return_val_if_fail (other != NULL, FALSE)do { if ((other != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "other != ((void*)0)"); return
((0)); } } while (0)
;
351
352 ENSURE_ALLOCATED (mask, mask_allocated)do { if (!(!(((gsize) (mask)) & 1))) { mask_allocated.data
[0] = (((gsize) (mask)) >> ((gsize) 1)); mask_allocated
.len = mask_allocated.data[0] ? 1 : 0; mask = &mask_allocated
; } } while (0)
;
353 ENSURE_ALLOCATED (other, other_allocated)do { if (!(!(((gsize) (other)) & 1))) { other_allocated.data
[0] = (((gsize) (other)) >> ((gsize) 1)); other_allocated
.len = other_allocated.data[0] ? 1 : 0; other = &other_allocated
; } } while (0)
;
354
355 for (i = MIN (mask->len, other->len)(((mask->len) < (other->len)) ? (mask->len) : (other
->len))
- 1; i >= 0; i--)
356 {
357 if (mask->data[i] & other->data[i])
358 return TRUE(!(0));
359 }
360
361 return FALSE(0);
362}
363