Bug Summary

File:src/games/number/number.c
Warning:line 280, column 10
2nd function call argument is an uninitialized 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 number.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 pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/games/number/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/games/number/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 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/games/number/number.c
1/* $OpenBSD: number.c,v 1.20 2016/03/07 12:07:56 mestre Exp $ */
2
3/*
4 * Copyright (c) 1988, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <ctype.h>
33#include <err.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <unistd.h>
38
39#define MAXNUM65 65 /* Biggest number we handle. */
40#define LINELEN256 256
41
42static const char *const name1[] = {
43 "", "one", "two", "three",
44 "four", "five", "six", "seven",
45 "eight", "nine", "ten", "eleven",
46 "twelve", "thirteen", "fourteen", "fifteen",
47 "sixteen", "seventeen", "eighteen", "nineteen",
48},
49 *const name2[] = {
50 "", "ten", "twenty", "thirty",
51 "forty", "fifty", "sixty", "seventy",
52 "eighty", "ninety",
53},
54 *const name3[] = {
55 "hundred", "thousand", "million", "billion",
56 "trillion", "quadrillion", "quintillion", "sextillion",
57 "septillion", "octillion", "nonillion", "decillion",
58 "undecillion", "duodecillion", "tredecillion", "quattuordecillion",
59 "quindecillion", "sexdecillion",
60 "septendecillion", "octodecillion",
61 "novemdecillion", "vigintillion",
62};
63
64void convert(char *);
65void convertexp(char *);
66int number(const char *, int);
67void pfract(int);
68int unit(int, const char *);
69__dead__attribute__((__noreturn__)) void usage(void);
70
71int lflag;
72
73int
74main(int argc, char *argv[])
75{
76 int ch, first;
77 char line[LINELEN256];
78
79 if (pledge("stdio", NULL((void *)0)) == -1)
1
Assuming the condition is false
2
Taking false branch
80 err(1, "pledge");
81
82 lflag = 0;
83 while ((ch = getopt(argc, argv, "hl")) != -1)
3
Assuming the condition is false
4
Loop condition is false. Execution continues on line 92
84 switch (ch) {
85 case 'l':
86 lflag = 1;
87 break;
88 case 'h':
89 default:
90 usage();
91 }
92 argc -= optind;
93 argv += optind;
94
95 if (*argv == NULL((void *)0))
5
Assuming the condition is false
6
Taking false branch
96 for (first = 1;
97 fgets(line, sizeof(line), stdin(&__sF[0])) != NULL((void *)0); first = 0) {
98 if (strchr(line, '\n') == NULL((void *)0))
99 errx(1, "line too long.");
100 if (!first)
101 (void)printf("...\n");
102 convert(line);
103 if (lflag)
104 (void)printf("\n");
105 }
106 else
107 for (first = 1; *argv != NULL((void *)0); first = 0, ++argv) {
7
Loop condition is true. Entering loop body
108 if (!first
7.1
'first' is 1
)
8
Taking false branch
109 (void)printf("...\n");
110 convert(*argv);
9
Calling 'convert'
111 if (lflag)
112 (void)printf("\n");
113 }
114 return 0;
115}
116
117void
118convert(char *line)
119{
120 int flen, len, rval;
121 char *p, *fraction;
122
123 /* strip trailing and leading whitespace */
124 len = strlen(line) - 1;
125 while ((isblank((unsigned char)line[len])) || (line[len] == '\n'))
10
Loop condition is false. Execution continues on line 127
126 line[len--] = '\0';
127 while ((isblank((unsigned char)line[0])) || (line[0] == '\n'))
11
Assuming the condition is false
12
Loop condition is false. Execution continues on line 129
128 line++;
129 if (strchr(line, 'e') || strchr(line, 'E'))
13
Assuming the condition is false
14
Assuming the condition is false
15
Taking false branch
130 convertexp(line);
131 else {
132 fraction = NULL((void *)0);
133 for (p = line; *p != '\0' && *p != '\n'; ++p) {
16
Assuming the condition is false
134 if (isblank((unsigned char)*p))
135 goto badnum;
136 if (isdigit((unsigned char)*p))
137 continue;
138 switch (*p) {
139 case '.':
140 if (fraction != NULL((void *)0))
141 goto badnum;
142 fraction = p + 1;
143 *p = '\0';
144 break;
145 case '-':
146 case '+':
147 if (p == line)
148 break;
149 /* FALLTHROUGH */
150 default:
151badnum: errx(1, "illegal number: %s", line);
152 break;
153 }
154 }
155 *p = '\0';
156
157 if ((len = strlen(line)) > MAXNUM65 ||
17
Assuming the condition is false
158 ((fraction
17.1
'fraction' is equal to NULL
!= NULL((void *)0)) && (flen = strlen(fraction)) > MAXNUM65))
159 errx(1, "number too long (max %d digits).", MAXNUM65);
160
161 if (*line == '-') {
18
Taking false branch
162 (void)printf("minus%s", lflag ? " " : "\n");
163 ++line;
164 --len;
165 }
166 if (*line == '+') {
19
Taking false branch
167 (void)printf("plus%s", lflag ? " " : "\n");
168 ++line;
169 --len;
170 }
171
172 rval = len > 0 ? unit(len, line) : 0;
20
Assuming 'len' is > 0
21
'?' condition is true
22
Calling 'unit'
173 if (fraction != NULL((void *)0) && flen != 0)
174 for (p = fraction; *p != '\0'; ++p)
175 if (*p != '0') {
176 if (rval)
177 (void)printf("%sand%s",
178 lflag ? " " : "",
179 lflag ? " " : "\n");
180 if (unit(flen, fraction)) {
181 if (lflag)
182 (void)printf(" ");
183 pfract(flen);
184 rval = 1;
185 }
186 break;
187 }
188 if (!rval)
189 (void)printf("zero%s", lflag ? "" : ".\n");
190 }
191}
192
193void
194convertexp(char *line)
195{
196 char locline[LINELEN256];
197 char *part1, *part2, *part3, *part4;
198 char tmp[2];
199 int i, j;
200
201 (void)strlcpy(locline,line,LINELEN256);
202 part3 = locline;
203 part2 = strsep(&part3, "eE"); /* part3 is the exponent */
204 part4 = part3;
205 (void)strsep(&part4, "."); /* no decimal allowed in the exponent */
206 if (part4)
207 errx(1, "illegal number: %s", line);
208 part1 = strsep(&part2, "."); /* we can have one in the mantissa */
209 /* At this point everything should be null or a digit. Check for
210 * that before starting to convert. Two characters may be + or -.
211 */
212 j = strlen(line);
213 for (i = 0; i < j; i++)
214 if ((!isdigit((unsigned char)locline[i])) && (locline[i]))
215 if (((locline[i] != '+') && (locline[i] != '-')) ||
216 ((i != 0) && (i != part3 - locline)))
217 errx(1, "illegal number: %s", line);
218 convert(part1);
219 printf("%s", lflag ? " " : "");
220 if (part2 && part2[0]) { /* do individual digits separately */
221 (void)printf("point%s", lflag ? " " : "\n");
222 j = strlen(part2); tmp[1] = '\0';
223 for (i = 0 ; i < j; i++ ) {
224 tmp[0] = part2[i];
225 convert(tmp);
226 (void)printf("%s", lflag ? " " : "");
227 }
228 }
229 (void)printf("times ten to the%s", lflag ? " " : "\n");
230 if (part3 && part3[0])
231 convert(part3);
232 else
233 (void)printf("zero%s", lflag ? " " : ".\n");
234}
235
236int
237unit(int len, const char *p)
238{
239 int off, rval;
240
241 rval = 0;
242 if (len > 3) {
23
Assuming 'len' is <= 3
24
Taking false branch
243 if (len % 3) {
244 off = len % 3;
245 len -= off;
246 if (number(p, off)) {
247 rval = 1;
248 (void)printf(" %s%s",
249 name3[len / 3], lflag ? " " : ".\n");
250 }
251 p += off;
252 }
253 for (; len > 3; p += 3) {
254 len -= 3;
255 if (number(p, 3)) {
256 rval = 1;
257 (void)printf(" %s%s",
258 name3[len / 3], lflag ? " " : ".\n");
259 }
260 }
261 }
262 if (number(p, len)) {
25
Calling 'number'
263 if (!lflag)
264 (void)printf(".\n");
265 rval = 1;
266 }
267 return (rval);
268}
269
270int
271number(const char *p, int len)
272{
273 int val, rval;
274
275 rval = 0;
276 switch (len) {
26
Control jumps to 'case 3:' at line 277
277 case 3:
278 if (*p != '0') {
27
Taking true branch
279 rval = 1;
280 (void)printf("%s hundred", name1[*p - '0']);
28
2nd function call argument is an uninitialized value
281 }
282 ++p;
283 /* FALLTHROUGH */
284 case 2:
285 val = (p[1] - '0') + (p[0] - '0') * 10;
286 if (val) {
287 if (rval)
288 (void)printf(" ");
289 if (val < 20)
290 (void)printf("%s", name1[val]);
291 else {
292 (void)printf("%s", name2[val / 10]);
293 if (val % 10)
294 (void)printf("-%s", name1[val % 10]);
295 }
296 rval = 1;
297 }
298 break;
299 case 1:
300 if (*p != '0') {
301 rval = 1;
302 (void)printf("%s", name1[*p - '0']);
303 }
304 }
305 return (rval);
306}
307
308void
309pfract(int len)
310{
311 static const char *const pref[] = { "", "ten-", "hundred-" };
312
313 switch(len) {
314 case 1:
315 (void)printf("tenths%s", lflag ? "" : ".\n");
316 break;
317 case 2:
318 (void)printf("hundredths%s", lflag ? "" : ".\n");
319 break;
320 default:
321 (void)printf("%s%sths%s", pref[len % 3], name3[len / 3],
322 lflag ? "" : ".\n");
323 break;
324 }
325}
326
327void
328usage(void)
329{
330 (void)fprintf(stderr(&__sF[2]), "usage: %s [-l] [--] [# ...]\n", getprogname());
331 exit(1);
332}