Bug Summary

File:s/cmd/btoa/btoa.c
Warning:line 124, column 22
Potential leak of memory pointed to by 'suffix'

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 btoa.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/btoa -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/btoa -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D NSPR20 -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 btoa.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#include "plgetopt.h"
6#include "secutil.h"
7#include "nssb64.h"
8#include <errno(*__errno_location ()).h>
9
10#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
11#if !defined(WIN32)
12extern int fread(char *, size_t, size_t, FILE *);
13extern int fwrite(char *, size_t, size_t, FILE *);
14extern int fprintf(FILE *, char *, ...);
15#endif
16#endif
17
18#if defined(WIN32)
19#include "fcntl.h"
20#include "io.h"
21#endif
22
23static PRInt32
24output_ascii(void *arg, const char *obuf, PRInt32 size)
25{
26 FILE *outFile = arg;
27 int nb;
28
29 nb = fwrite(obuf, 1, size, outFile);
30 if (nb != size) {
31 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_IO);
32 return -1;
33 }
34
35 return nb;
36}
37
38static SECStatus
39encode_file(FILE *outFile, FILE *inFile)
40{
41 NSSBase64Encoder *cx;
42 int nb;
43 SECStatus status = SECFailure;
44 unsigned char ibuf[4096];
45
46 cx = NSSBase64Encoder_CreateNSSBase64Encoder_Create_Util(output_ascii, outFile);
47 if (!cx) {
48 return -1;
49 }
50
51 for (;;) {
52 if (feof(inFile))
53 break;
54 nb = fread(ibuf, 1, sizeof(ibuf), inFile);
55 if (nb != sizeof(ibuf)) {
56 if (nb == 0) {
57 if (ferror(inFile)) {
58 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_IO);
59 goto loser;
60 }
61 /* eof */
62 break;
63 }
64 }
65
66 status = NSSBase64Encoder_UpdateNSSBase64Encoder_Update_Util(cx, ibuf, nb);
67 if (status != SECSuccess)
68 goto loser;
69 }
70
71 status = NSSBase64Encoder_DestroyNSSBase64Encoder_Destroy_Util(cx, PR_FALSE0);
72 if (status != SECSuccess)
73 return status;
74
75 /*
76 * Add a trailing CRLF. Note this must be done *after* the call
77 * to Destroy above (because only then are we sure all data has
78 * been written out).
79 */
80 fwrite("\r\n", 1, 2, outFile);
81 return SECSuccess;
82
83loser:
84 (void)NSSBase64Encoder_DestroyNSSBase64Encoder_Destroy_Util(cx, PR_TRUE1);
85 return status;
86}
87
88static void
89Usage(char *progName)
90{
91 fprintf(stderrstderr,
92 "Usage: %s [-i input] [-o output]\n",
93 progName);
94 fprintf(stderrstderr, "%-20s Define an input file to use (default is stdin)\n",
95 "-i input");
96 fprintf(stderrstderr, "%-20s Define an output file to use (default is stdout)\n",
97 "-o output");
98 fprintf(stderrstderr, "%-20s Wrap output in BEGIN/END lines and the given suffix\n",
99 "-w suffix");
100 fprintf(stderrstderr, "%-20s (use \"c\" as a shortcut for suffix CERTIFICATE)\n",
101 "");
102}
103
104int
105main(int argc, char **argv)
106{
107 char *progName;
108 SECStatus rv;
109 FILE *inFile = NULL((void*)0), *outFile = NULL((void*)0);
110 PRBool closeIn = PR_TRUE1, closeOut = PR_TRUE1;
111 PLOptState *optstate = NULL((void*)0);
112 PLOptStatus status;
113 char *suffix = NULL((void*)0);
114 int exitCode = -1;
115
116 progName = strrchr(argv[0], '/');
117 if (!progName)
1
Assuming 'progName' is non-null
118 progName = strrchr(argv[0], '\\');
119 progName = progName
2.1
'progName' is non-null
? progName + 1 : argv[0];
2
Taking false branch
3
'?' condition is true
120
121 /* Parse command line arguments */
122 optstate = PL_CreateOptState(argc, argv, "i:o:w:");
123 PORT_Assert(optstate)((optstate)?((void)0):PR_Assert("optstate","btoa.c",123));
4
Assuming 'optstate' is non-null
5
'?' condition is true
124 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
6
Assuming the condition is true
7
Loop condition is true. Entering loop body
11
Execution continues on line 124
12
Assuming the condition is true
13
Loop condition is true. Entering loop body
16
Execution continues on line 124
17
Potential leak of memory pointed to by 'suffix'
125 switch (optstate->option) {
8
Control jumps to 'case 119:' at line 149
14
Control jumps to 'case 119:' at line 149
126 default:
127 Usage(progName);
128 goto loser;
129 break;
130
131 case 'i':
132 inFile = fopen(optstate->value, "rb");
133 if (!inFile) {
134 fprintf(stderrstderr, "%s: unable to open \"%s\" for reading\n",
135 progName, optstate->value);
136 goto loser;
137 }
138 break;
139
140 case 'o':
141 outFile = fopen(optstate->value, "wb");
142 if (!outFile) {
143 fprintf(stderrstderr, "%s: unable to open \"%s\" for writing\n",
144 progName, optstate->value);
145 goto loser;
146 }
147 break;
148
149 case 'w':
150 if (!strcmp(optstate->value, "c"))
9
Taking true branch
15
Taking true branch
151 suffix = strdup("CERTIFICATE");
10
Memory is allocated
152 else
153 suffix = strdup(optstate->value);
154 break;
155 }
156 }
157 if (status == PL_OPT_BAD)
158 Usage(progName);
159 if (!inFile) {
160#if defined(WIN32)
161 /* If we're going to read binary data from stdin, we must put stdin
162 ** into O_BINARY mode or else incoming \r\n's will become \n's.
163 */
164
165 int smrv = _setmode(_fileno(stdinstdin), _O_BINARY);
166 if (smrv == -1) {
167 fprintf(stderrstderr,
168 "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
169 progName);
170 goto loser;
171 }
172#endif
173 inFile = stdinstdin;
174 closeIn = PR_FALSE0;
175 }
176 if (!outFile) {
177#if defined(WIN32)
178 /* We're going to write binary data to stdout. We must put stdout
179 ** into O_BINARY mode or else outgoing \r\n's will become \r\r\n's.
180 */
181
182 int smrv = _setmode(_fileno(stdoutstdout), _O_BINARY);
183 if (smrv == -1) {
184 fprintf(stderrstderr,
185 "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
186 progName);
187 goto loser;
188 }
189#endif
190 outFile = stdoutstdout;
191 closeOut = PR_FALSE0;
192 }
193 if (suffix) {
194 fprintf(outFile, "-----BEGIN %s-----\n", suffix);
195 }
196 rv = encode_file(outFile, inFile);
197 if (rv != SECSuccess) {
198 fprintf(stderrstderr, "%s: lossage: error=%d errno=%d\n",
199 progName, PORT_GetErrorPORT_GetError_Util(), errno(*__errno_location ()));
200 goto loser;
201 }
202 if (suffix) {
203 fprintf(outFile, "-----END %s-----\n", suffix);
204 }
205 exitCode = 0;
206loser:
207 PL_DestroyOptState(optstate);
208 if (inFile && closeIn) {
209 fclose(inFile);
210 }
211 if (outFile && closeOut) {
212 fclose(outFile);
213 }
214 if (suffix) {
215 PORT_FreePORT_Free_Util(suffix);
216 }
217 return exitCode;
218}