Bug Summary

File:dev/pci/drm/linux_radix.c
Warning:line 233, column 27
The left operand of '==' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name linux_radix.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/pci/drm/linux_radix.c
1/*-
2 * Copyright (c) 2010 Isilon Systems, Inc.
3 * Copyright (c) 2010 iX Systems, Inc.
4 * Copyright (c) 2010 Panasas, Inc.
5 * Copyright (c) 2013-2018 Mellanox Technologies, Ltd.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice unmodified, this list of conditions, and the following
13 * disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/* $FreeBSD: head/sys/compat/linuxkpi/common/src/linux_radix.c 334483 2018-06-01 11:42:09Z hselasky $ */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/malloc.h>
35#include <sys/kernel.h>
36#include <sys/sysctl.h>
37
38#include <linux/radix-tree.h>
39
40#define M_RADIX145 M_DRM145
41
42static inline unsigned long
43radix_max(struct radix_tree_root *root)
44{
45 return ((1UL << (root->height * RADIX_TREE_MAP_SHIFT6)) - 1UL);
46}
47
48static inline int
49radix_pos(long id, int height)
50{
51 return (id >> (RADIX_TREE_MAP_SHIFT6 * height)) & RADIX_TREE_MAP_MASK((1UL << 6) - 1UL);
52}
53
54void *
55radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
56{
57 struct radix_tree_node *node;
58 void *item;
59 int height;
60
61 item = NULL((void *)0);
62 node = root->rnode;
63 height = root->height - 1;
64 if (index > radix_max(root))
65 goto out;
66 while (height && node)
67 node = node->slots[radix_pos(index, height--)];
68 if (node)
69 item = node->slots[radix_pos(index, 0)];
70
71out:
72 return (item);
73}
74
75bool_Bool
76radix_tree_iter_find(struct radix_tree_root *root, struct radix_tree_iter *iter,
77 void ***pppslot)
78{
79 struct radix_tree_node *node;
80 unsigned long index = iter->index;
81 int height;
82
83restart:
84 node = root->rnode;
85 if (node == NULL((void *)0))
86 return (false0);
87 height = root->height - 1;
88 if (height == -1 || index > radix_max(root))
89 return (false0);
90 do {
91 unsigned long mask = RADIX_TREE_MAP_MASK((1UL << 6) - 1UL) << (RADIX_TREE_MAP_SHIFT6 * height);
92 unsigned long step = 1UL << (RADIX_TREE_MAP_SHIFT6 * height);
93 int pos = radix_pos(index, height);
94 struct radix_tree_node *next;
95
96 /* track last slot */
97 *pppslot = node->slots + pos;
98
99 next = node->slots[pos];
100 if (next == NULL((void *)0)) {
101 index += step;
102 index &= -step;
103 if ((index & mask) == 0)
104 goto restart;
105 } else {
106 node = next;
107 height--;
108 }
109 } while (height != -1);
110 iter->index = index;
111 return (true1);
112}
113
114void *
115radix_tree_delete(struct radix_tree_root *root, unsigned long index)
116{
117 struct radix_tree_node *stack[RADIX_TREE_MAX_HEIGHT(((sizeof(long) * 8) + ((6) - 1)) / (6))];
118 struct radix_tree_node *node;
119 void *item;
120 int height;
121 int idx;
122
123 item = NULL((void *)0);
124 node = root->rnode;
125 height = root->height - 1;
126 if (index > radix_max(root))
127 goto out;
128 /*
129 * Find the node and record the path in stack.
130 */
131 while (height && node) {
132 stack[height] = node;
133 node = node->slots[radix_pos(index, height--)];
134 }
135 idx = radix_pos(index, 0);
136 if (node)
137 item = node->slots[idx];
138 /*
139 * If we removed something reduce the height of the tree.
140 */
141 if (item)
142 for (;;) {
143 node->slots[idx] = NULL((void *)0);
144 node->count--;
145 if (node->count > 0)
146 break;
147 free(node, M_RADIX145, sizeof(*node));
148 if (node == root->rnode) {
149 root->rnode = NULL((void *)0);
150 root->height = 0;
151 break;
152 }
153 height++;
154 node = stack[height];
155 idx = radix_pos(index, height);
156 }
157out:
158 return (item);
159}
160
161void
162radix_tree_iter_delete(struct radix_tree_root *root,
163 struct radix_tree_iter *iter, void **slot)
164{
165 radix_tree_delete(root, iter->index);
166}
167
168int
169radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item)
170{
171 struct radix_tree_node *node;
172 struct radix_tree_node *temp[RADIX_TREE_MAX_HEIGHT(((sizeof(long) * 8) + ((6) - 1)) / (6)) - 1];
173 int height;
174 int idx;
175
176 /* bail out upon insertion of a NULL item */
177 if (item == NULL((void *)0))
1
Assuming 'item' is not equal to NULL
2
Taking false branch
178 return (-EINVAL22);
179
180 /* get root node, if any */
181 node = root->rnode;
182
183 /* allocate root node, if any */
184 if (node == NULL((void *)0)) {
3
Assuming 'node' is equal to NULL
4
Taking true branch
185 node = malloc(sizeof(*node), M_RADIX145, root->gfp_mask | M_ZERO0x0008);
5
Uninitialized value stored to field 'count'
186 if (node == NULL((void *)0))
6
Assuming 'node' is not equal to NULL
7
Taking false branch
187 return (-ENOMEM12);
188 root->rnode = node;
189 root->height++;
190 }
191
192 /* expand radix tree as needed */
193 while (radix_max(root) < index) {
8
Assuming the condition is false
9
Loop condition is false. Execution continues on line 215
194
195 /* check if the radix tree is getting too big */
196 if (root->height == RADIX_TREE_MAX_HEIGHT(((sizeof(long) * 8) + ((6) - 1)) / (6)))
197 return (-E2BIG7);
198
199 /*
200 * If the root radix level is not empty, we need to
201 * allocate a new radix level:
202 */
203 if (node->count != 0) {
204 node = malloc(sizeof(*node), M_RADIX145, root->gfp_mask | M_ZERO0x0008);
205 if (node == NULL((void *)0))
206 return (-ENOMEM12);
207 node->slots[0] = root->rnode;
208 node->count++;
209 root->rnode = node;
210 }
211 root->height++;
212 }
213
214 /* get radix tree height index */
215 height = root->height - 1;
216
217 /* walk down the tree until the first missing node, if any */
218 for ( ; height != 0; height--) {
10
Assuming 'height' is not equal to 0
11
Loop condition is true. Entering loop body
219 idx = radix_pos(index, height);
220 if (node->slots[idx] == NULL((void *)0))
12
Assuming the condition is true
13
Taking true branch
221 break;
14
Execution continues on line 226
222 node = node->slots[idx];
223 }
224
225 /* allocate the missing radix levels, if any */
226 for (idx = 0; idx
14.1
'idx' is not equal to 'height'
!= height; idx++) {
15
Loop condition is true. Entering loop body
227 temp[idx] = malloc(sizeof(*node), M_RADIX145,
228 root->gfp_mask | M_ZERO0x0008);
229 if (temp[idx] == NULL((void *)0)) {
16
Assuming the condition is true
17
Taking true branch
230 while(idx--)
18
Loop condition is false. Execution continues on line 233
231 free(temp[idx], M_RADIX145, sizeof(*node));
232 /* Check if we should free the root node as well. */
233 if (root->rnode->count == 0) {
19
The left operand of '==' is a garbage value
234 free(root->rnode, M_RADIX145, sizeof(*root->rnode));
235 root->rnode = NULL((void *)0);
236 root->height = 0;
237 }
238 return (-ENOMEM12);
239 }
240 }
241
242 /* setup new radix levels, if any */
243 for ( ; height != 0; height--) {
244 idx = radix_pos(index, height);
245 node->slots[idx] = temp[height - 1];
246 node->count++;
247 node = node->slots[idx];
248 }
249
250 /*
251 * Insert and adjust count if the item does not already exist.
252 */
253 idx = radix_pos(index, 0);
254 if (node->slots[idx])
255 return (-EEXIST17);
256 node->slots[idx] = item;
257 node->count++;
258
259 return (0);
260}