Bug Summary

File:s/cmd/dbtest/dbtest.c
Warning:line 137, column 9
Array access (from variable 'dbDir') results in a null pointer dereference

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 dbtest.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 -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/dbtest -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/dbtest -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -I ../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -I ../../../dist/public/seccmd -I ../../../dist/public/dbm -internal-isystem /usr/lib/llvm-18/lib/clang/18/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 -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c dbtest.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** dbtest.c
7**
8** QA test for cert and key databases, especially to open
9** database readonly (NSS_INIT_READONLY) and force initializations
10** even if the databases cannot be opened (NSS_INIT_FORCEOPEN)
11**
12*/
13#include <stdio.h>
14#include <string.h>
15
16#if defined(WIN32)
17#include "fcntl.h"
18#include "io.h"
19#endif
20
21#include "secutil.h"
22#include "pk11pub.h"
23
24#if defined(XP_UNIX1)
25#include <unistd.h>
26#endif
27
28#include "nspr.h"
29#include "prtypes.h"
30#include "certdb.h"
31#include "nss.h"
32#include "../modutil/modutil.h"
33
34#include "plgetopt.h"
35
36static char *progName;
37
38char *dbDir = NULL((void*)0);
39
40static char *dbName[] = { "secmod.db", "cert8.db", "key3.db" };
41static char *dbprefix = "";
42static char *secmodName = "secmod.db";
43static char *userPassword = "";
44PRBool verbose;
45
46static char *
47getPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
48{
49 int *success = (int *)arg;
50
51 if (retry) {
52 *success = 0;
53 return NULL((void*)0);
54 }
55
56 *success = 1;
57 return PORT_StrdupPORT_Strdup_Util(userPassword);
58}
59
60static void
61Usage()
62{
63 printf("Usage: %s [-r] [-f] [-i] [-d dbdir ] \n",
64 progName);
65 printf("%-20s open database readonly (NSS_INIT_READONLY)\n", "-r");
66 printf("%-20s Continue to force initializations even if the\n", "-f");
67 printf("%-20s databases cannot be opened (NSS_INIT_FORCEOPEN)\n", " ");
68 printf("%-20s Try to initialize the database\n", "-i");
69 printf("%-20s Supply a password with which to initialize the db\n", "-p");
70 printf("%-20s Directory with cert database (default is .\n",
71 "-d certdir");
72 exit(1);
73}
74
75int
76main(int argc, char **argv)
77{
78 PLOptState *optstate;
79 PLOptStatus optstatus;
80
81 PRUint32 flags = 0;
82 Error ret;
83 SECStatus rv;
84 char *dbString = NULL((void*)0);
85 PRBool doInitTest = PR_FALSE0;
86 int i;
87
88 progName = strrchr(argv[0], '/');
89 if (!progName)
1
Assuming 'progName' is non-null
90 progName = strrchr(argv[0], '\\');
91 progName = progName
2.1
'progName' is non-null
? progName + 1 : argv[0];
2
Taking false branch
3
'?' condition is true
92
93 optstate = PL_CreateOptState(argc, argv, "rfip:d:h");
94
95 while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
4
Assuming the condition is false
5
Loop condition is false. Execution continues on line 123
96 switch (optstate->option) {
97 case 'h':
98 default:
99 Usage();
100 break;
101
102 case 'r':
103 flags |= NSS_INIT_READONLY0x1;
104 break;
105
106 case 'f':
107 flags |= NSS_INIT_FORCEOPEN0x8;
108 break;
109
110 case 'i':
111 doInitTest = PR_TRUE1;
112 break;
113
114 case 'p':
115 userPassword = PORT_StrdupPORT_Strdup_Util(optstate->value);
116 break;
117
118 case 'd':
119 dbDir = PORT_StrdupPORT_Strdup_Util(optstate->value);
120 break;
121 }
122 }
123 PL_DestroyOptState(optstate);
124 if (optstatus == PL_OPT_BAD)
6
Assuming 'optstatus' is not equal to PL_OPT_BAD
7
Taking false branch
125 Usage();
126
127 if (dbDir
7.1
'dbDir' is null
) {
8
Taking false branch
128 char *tmp = dbDir;
129 dbDir = SECU_ConfigDirectory(tmp);
130 PORT_FreePORT_Free_Util(tmp);
131 } else {
132 /* Look in $SSL_DIR */
133 dbDir = SECU_ConfigDirectory(SECU_DefaultSSLDir());
134 }
135 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "dbdir selected is %s\n\n", dbDir);
9
Null pointer value stored to 'dbDir'
136
137 if (dbDir[0] == '\0') {
10
Array access (from variable 'dbDir') results in a null pointer dereference
138 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
139 ret = DIR_DOESNT_EXIST_ERR;
140 goto loser;
141 }
142
143 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
144
145 /* get the status of the directory and databases and output message */
146 if (PR_Access(dbDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
147 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
148 } else if (PR_Access(dbDir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
149 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), errStrings[DIR_NOT_READABLE_ERR], dbDir);
150 } else {
151 if (!(flags & NSS_INIT_READONLY0x1) &&
152 PR_Access(dbDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
153 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), errStrings[DIR_NOT_WRITEABLE_ERR], dbDir);
154 }
155 if (!doInitTest) {
156 for (i = 0; i < 3; i++) {
157 dbString = PR_smprintf("%s/%s", dbDir, dbName[i]);
158 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "database checked is %s\n", dbString);
159 if (PR_Access(dbString, PR_ACCESS_EXISTS) != PR_SUCCESS) {
160 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), errStrings[FILE_DOESNT_EXIST_ERR],
161 dbString);
162 } else if (PR_Access(dbString, PR_ACCESS_READ_OK) != PR_SUCCESS) {
163 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), errStrings[FILE_NOT_READABLE_ERR],
164 dbString);
165 } else if (!(flags & NSS_INIT_READONLY0x1) &&
166 PR_Access(dbString, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
167 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), errStrings[FILE_NOT_WRITEABLE_ERR],
168 dbString);
169 }
170 PR_smprintf_free(dbString);
171 }
172 }
173 }
174
175 rv = NSS_Initialize(SECU_ConfigDirectory(dbDir), dbprefix, dbprefix,
176 secmodName, flags);
177 if (rv != SECSuccess) {
178 SECU_PrintPRandOSError(progName);
179 ret = NSS_INITIALIZE_FAILED_ERR;
180 } else {
181 ret = SUCCESSNO_ERR;
182 if (doInitTest) {
183 PK11SlotInfo *slot = PK11_GetInternalKeySlot();
184 int passwordSuccess = 0;
185 int type = CKM_DES3_CBC0x00000133UL;
186 SECItem keyid = { 0, NULL((void*)0), 0 };
187 unsigned char keyIdData[] = { 0xff, 0xfe };
188 PK11SymKey *key = NULL((void*)0);
189
190 keyid.data = keyIdData;
191 keyid.len = sizeof(keyIdData);
192
193 PK11_SetPasswordFunc(getPassword);
194 rv = PK11_InitPin(slot, (char *)NULL((void*)0), userPassword);
195 if (rv != SECSuccess) {
196 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Failed to Init DB: %s\n",
197 SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
198 ret = CHANGEPW_FAILED_ERR;
199 }
200 if (*userPassword && !PK11_IsLoggedIn(slot, &passwordSuccess)) {
201 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "New DB did not log in after init\n");
202 ret = AUTHENTICATION_FAILED_ERR;
203 }
204 /* generate a symetric key */
205 key = PK11_TokenKeyGen(slot, type, NULL((void*)0), 0, &keyid,
206 PR_TRUE1, &passwordSuccess);
207
208 if (!key) {
209 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Could not generated symetric key: %s\n",
210 SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
211 exit(UNSPECIFIED_ERR);
212 }
213 PK11_FreeSymKey(key);
214 PK11_Logout(slot);
215
216 PK11_Authenticate(slot, PR_TRUE1, &passwordSuccess);
217
218 if (*userPassword && !passwordSuccess) {
219 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "New DB Did not initalize\n");
220 ret = AUTHENTICATION_FAILED_ERR;
221 }
222 key = PK11_FindFixedKey(slot, type, &keyid, &passwordSuccess);
223
224 if (!key) {
225 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Could not find generated key: %s\n",
226 SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
227 ret = UNSPECIFIED_ERR;
228 } else {
229 PK11_FreeSymKey(key);
230 }
231 PK11_FreeSlot(slot);
232 }
233
234 if (NSS_Shutdown() != SECSuccess) {
235 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Could not find generated key: %s\n",
236 SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
237 exit(1);
238 }
239 }
240
241loser:
242 return ret;
243}