Bug Summary

File:root/firefox-clang/security/nss/lib/ckfw/hash.c
Warning:line 49, column 39
Subtraction of a probably non-null pointer and a null pointer may result in undefined behavior

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name hash.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 -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/ckfw/ckfw_nssckfw -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/ckfw/ckfw_nssckfw -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG -D NSS_FIPS_DISABLED -D NSS_NO_INIT_SUPPORT -D NSS_X86_OR_X64 -D NSS_X64 -D NSS_USE_64 -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -D LINUX2_1 -D LINUX -D linux -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D HAVE_STRERROR -D XP_UNIX -D _REENTRANT -D NSS_DISABLE_DBM -D NSS_DISABLE_LIBPKIX -D NSS_USE_PKCS5_PBKD2_PARAMS2_ONLY -D SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY -I /root/firefox-clang/security/nss/lib/ckfw -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/ckfw/ckfw_nssckfw -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/private/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c /root/firefox-clang/security/nss/lib/ckfw/hash.c
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5/*
6 * hash.c
7 *
8 * This is merely a couple wrappers around NSPR's PLHashTable, using
9 * the identity hash and arena-aware allocators. The reason I did
10 * this is that hash tables are used in a few places throughout the
11 * NSS Cryptoki Framework in a fairly stereotyped way, and this allows
12 * me to pull the commonalities into one place. Should we ever want
13 * to change the implementation, it's all right here.
14 */
15
16#ifndef CK_T
17#include "ck.h"
18#endif /* CK_T */
19
20/*
21 * nssCKFWHash
22 *
23 * nssCKFWHash_Create
24 * nssCKFWHash_Destroy
25 * nssCKFWHash_Add
26 * nssCKFWHash_Remove
27 * nssCKFWHash_Count
28 * nssCKFWHash_Exists
29 * nssCKFWHash_Lookup
30 * nssCKFWHash_Iterate
31 */
32
33struct nssCKFWHashStr {
34 NSSCKFWMutex *mutex;
35
36 /*
37 * The invariant that mutex protects is:
38 * The count accurately reflects the hashtable state.
39 */
40
41 PLHashTable *plHashTable;
42 CK_ULONG count;
43};
44
45static PLHashNumber
46nss_ckfw_identity_hash(
47 const void *key)
48{
49 return (PLHashNumber)((char *)key - (char *)NULL((void*)0));
Subtraction of a probably non-null pointer and a null pointer may result in undefined behavior
50}
51
52/*
53 * nssCKFWHash_Create
54 *
55 */
56NSS_IMPLEMENT nssCKFWHash *
57nssCKFWHash_Create(
58 NSSCKFWInstance *fwInstance,
59 NSSArena *arena,
60 CK_RV *pError)
61{
62 nssCKFWHash *rv;
63
64#ifdef NSSDEBUG
65 if (!pError) {
66 return (nssCKFWHash *)NULL((void*)0);
67 }
68
69 if (PR_SUCCESS != nssArena_verifyPointer(arena)) {
70 *pError = CKR_ARGUMENTS_BAD0x00000007UL;
71 return (nssCKFWHash *)NULL((void*)0);
72 }
73#endif /* NSSDEBUG */
74
75 rv = nss_ZNEW(arena, nssCKFWHash)((nssCKFWHash *)nss_ZAlloc((arena), sizeof(nssCKFWHash)));
76 if (!rv) {
77 *pError = CKR_HOST_MEMORY0x00000002UL;
78 return (nssCKFWHash *)NULL((void*)0);
79 }
80
81 rv->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError);
82 if (!rv->mutex) {
83 if (CKR_OK0x00000000UL == *pError) {
84 *pError = CKR_GENERAL_ERROR0x00000005UL;
85 }
86 (void)nss_ZFreeIf(rv);
87 return (nssCKFWHash *)NULL((void*)0);
88 }
89
90 rv->plHashTable = PL_NewHashTable(0, nss_ckfw_identity_hash,
91 PL_CompareValues, PL_CompareValues, &nssArenaHashAllocOps, arena);
92 if (!rv->plHashTable) {
93 (void)nssCKFWMutex_Destroy(rv->mutex);
94 (void)nss_ZFreeIf(rv);
95 *pError = CKR_HOST_MEMORY0x00000002UL;
96 return (nssCKFWHash *)NULL((void*)0);
97 }
98
99 rv->count = 0;
100
101 return rv;
102}
103
104/*
105 * nssCKFWHash_Destroy
106 *
107 */
108NSS_IMPLEMENT void
109nssCKFWHash_Destroy(
110 nssCKFWHash *hash)
111{
112 (void)nssCKFWMutex_Destroy(hash->mutex);
113 PL_HashTableDestroy(hash->plHashTable);
114 (void)nss_ZFreeIf(hash);
115}
116
117/*
118 * nssCKFWHash_Add
119 *
120 */
121NSS_IMPLEMENT CK_RV
122nssCKFWHash_Add(
123 nssCKFWHash *hash,
124 const void *key,
125 const void *value)
126{
127 CK_RV error = CKR_OK0x00000000UL;
128 PLHashEntry *he;
129
130 error = nssCKFWMutex_Lock(hash->mutex);
131 if (CKR_OK0x00000000UL != error) {
132 return error;
133 }
134
135 he = PL_HashTableAdd(hash->plHashTable, key, (void *)value);
136 if (!he) {
137 error = CKR_HOST_MEMORY0x00000002UL;
138 } else {
139 hash->count++;
140 }
141
142 (void)nssCKFWMutex_Unlock(hash->mutex);
143
144 return error;
145}
146
147/*
148 * nssCKFWHash_Remove
149 *
150 */
151NSS_IMPLEMENT void
152nssCKFWHash_Remove(
153 nssCKFWHash *hash,
154 const void *it)
155{
156 PRBool found;
157
158 if (CKR_OK0x00000000UL != nssCKFWMutex_Lock(hash->mutex)) {
159 return;
160 }
161
162 found = PL_HashTableRemove(hash->plHashTable, it);
163 if (found) {
164 hash->count--;
165 }
166
167 (void)nssCKFWMutex_Unlock(hash->mutex);
168 return;
169}
170
171/*
172 * nssCKFWHash_Count
173 *
174 */
175NSS_IMPLEMENT CK_ULONG
176nssCKFWHash_Count(
177 nssCKFWHash *hash)
178{
179 CK_ULONG count;
180
181 if (CKR_OK0x00000000UL != nssCKFWMutex_Lock(hash->mutex)) {
182 return (CK_ULONG)0;
183 }
184
185 count = hash->count;
186
187 (void)nssCKFWMutex_Unlock(hash->mutex);
188
189 return count;
190}
191
192/*
193 * nssCKFWHash_Exists
194 *
195 */
196NSS_IMPLEMENT CK_BBOOL
197nssCKFWHash_Exists(
198 nssCKFWHash *hash,
199 const void *it)
200{
201 void *value;
202
203 if (CKR_OK0x00000000UL != nssCKFWMutex_Lock(hash->mutex)) {
204 return CK_FALSE0;
205 }
206
207 value = PL_HashTableLookup(hash->plHashTable, it);
208
209 (void)nssCKFWMutex_Unlock(hash->mutex);
210
211 if (!value) {
212 return CK_FALSE0;
213 } else {
214 return CK_TRUE1;
215 }
216}
217
218/*
219 * nssCKFWHash_Lookup
220 *
221 */
222NSS_IMPLEMENT void *
223nssCKFWHash_Lookup(
224 nssCKFWHash *hash,
225 const void *it)
226{
227 void *rv;
228
229 if (CKR_OK0x00000000UL != nssCKFWMutex_Lock(hash->mutex)) {
230 return (void *)NULL((void*)0);
231 }
232
233 rv = PL_HashTableLookup(hash->plHashTable, it);
234
235 (void)nssCKFWMutex_Unlock(hash->mutex);
236
237 return rv;
238}
239
240struct arg_str {
241 nssCKFWHashIterator fcn;
242 void *closure;
243};
244
245static PRIntn
246nss_ckfwhash_enumerator(
247 PLHashEntry *he,
248 PRIntn index,
249 void *arg)
250{
251 struct arg_str *as = (struct arg_str *)arg;
252 as->fcn(he->key, he->value, as->closure);
253 return HT_ENUMERATE_NEXT0;
254}
255
256/*
257 * nssCKFWHash_Iterate
258 *
259 * NOTE that the iteration function will be called with the hashtable locked.
260 */
261NSS_IMPLEMENT void
262nssCKFWHash_Iterate(
263 nssCKFWHash *hash,
264 nssCKFWHashIterator fcn,
265 void *closure)
266{
267 struct arg_str as;
268 as.fcn = fcn;
269 as.closure = closure;
270
271 if (CKR_OK0x00000000UL != nssCKFWMutex_Lock(hash->mutex)) {
272 return;
273 }
274
275 PL_HashTableEnumerateEntries(hash->plHashTable, nss_ckfwhash_enumerator, &as);
276
277 (void)nssCKFWMutex_Unlock(hash->mutex);
278
279 return;
280}