Bug Summary

File:src/lib/libcurses/tinfo/lib_tgoto.c
Warning:line 180, column 15
Null pointer passed as 2nd argument to string copy function

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 lib_tgoto.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 -fhalf-no-semantic-interposition -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/lib/libcurses/obj -resource-dir /usr/local/lib/clang/13.0.0 -I . -I /usr/src/lib/libcurses -D PIC -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcurses/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/lib/libcurses/tinfo/lib_tgoto.c
1/* $OpenBSD: lib_tgoto.c,v 1.6 2010/01/14 22:53:22 nicm Exp $ */
2
3/****************************************************************************
4 * Copyright (c) 2000-2006,2008 Free Software Foundation, Inc. *
5 * *
6 * Permission is hereby granted, free of charge, to any person obtaining a *
7 * copy of this software and associated documentation files (the *
8 * "Software"), to deal in the Software without restriction, including *
9 * without limitation the rights to use, copy, modify, merge, publish, *
10 * distribute, distribute with modifications, sublicense, and/or sell *
11 * copies of the Software, and to permit persons to whom the Software is *
12 * furnished to do so, subject to the following conditions: *
13 * *
14 * The above copyright notice and this permission notice shall be included *
15 * in all copies or substantial portions of the Software. *
16 * *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
20 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
23 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
24 * *
25 * Except as contained in this notice, the name(s) of the above copyright *
26 * holders shall not be used in advertising or otherwise to promote the *
27 * sale, use or other dealings in this Software without prior written *
28 * authorization. *
29 ****************************************************************************/
30
31/****************************************************************************
32 * Author: Thomas E. Dickey *
33 ****************************************************************************/
34
35#include <curses.priv.h>
36
37#include <ctype.h>
38#include <termcap.h>
39
40MODULE_ID("$Id: lib_tgoto.c,v 1.6 2010/01/14 22:53:22 nicm Exp $")
41
42#if !PURE_TERMINFO0
43static bool_Bool
44is_termcap(const char *string)
45{
46 bool_Bool result = TRUE1;
47
48 if (string == 0 || *string == '\0') {
49 result = FALSE0; /* tparm() handles empty strings */
50 } else {
51 while ((*string != '\0') && result) {
52 if (*string == '%') {
53 switch (*++string) {
54 case 'p':
55 result = FALSE0;
56 break;
57 case '\0':
58 string--;
59 break;
60 }
61 } else if (string[0] == '$' && string[1] == '<') {
62 result = FALSE0;
63 }
64 string++;
65 }
66 }
67 return result;
68}
69
70static char *
71tgoto_internal(const char *string, int x, int y)
72{
73 static char *result;
74 static size_t length;
75
76 int swap_arg;
77 int param[3];
78 size_t used = 0;
79 size_t need = 10;
80 size_t copied;
81 int *value = param;
82 bool_Bool need_BC = FALSE0;
83
84 if (BC)
3
Assuming 'BC' is null
4
Taking false branch
85 need += strlen(BC);
86
87 param[0] = y;
88 param[1] = x;
89 param[2] = 0;
90
91 while (*string != 0) {
5
Loop condition is true. Entering loop body
18
Assuming the condition is true
19
Loop condition is true. Entering loop body
34
Assuming the condition is false
35
Loop condition is false. Execution continues on line 178
92 if ((used + need) > length) {
6
Taking true branch
20
Taking true branch
93 length += (used + need);
94 if ((result = typeRealloc(char, length, result)(char *)_nc_doalloc(result, (length)*sizeof(char))) == 0) {
7
Assuming the condition is false
8
Taking false branch
21
Value assigned to 'BC'
22
Assuming the condition is false
23
Taking false branch
95 length = 0;
96 break;
97 }
98 }
99 if (*string == '%') {
9
Taking true branch
24
Assuming the condition is true
25
Taking true branch
100 const char *fmt = 0;
101
102 switch (*++string) {
10
Control jumps to 'case 43:' at line 117
26
Control jumps to 'case 46:' at line 120
103 case '\0':
104 string--;
105 break;
106 case 'd':
107 fmt = "%d";
108 break;
109 case '2':
110 fmt = "%02d";
111 *value %= 100;
112 break;
113 case '3':
114 fmt = "%03d";
115 *value %= 1000;
116 break;
117 case '+':
118 *value += UChar(*++string)((unsigned char)(*++string));
119 /* FALLTHRU */
120 case '.':
121 /*
122 * Guard against tputs() seeing a truncated string. The
123 * termcap documentation refers to a similar fixup for \n
124 * and \r, but I don't see that it could work -TD
125 */
126 if (*value == 0) {
11
Assuming the condition is true
12
Taking true branch
27
Assuming the condition is true
28
Taking true branch
127 if (BC != 0) {
13
Assuming 'BC' is not equal to null
14
Taking true branch
29
Assuming 'BC' is equal to null
30
Taking false branch
128 *value += 1;
129 need_BC = TRUE1;
130 } else {
131 *value = 0200; /* tputs will treat this as \0 */
132 }
133 }
134 result[used++] = (char) *value++;
135 break;
15
Execution continues on line 164
31
Execution continues on line 164
136 case '%':
137 result[used++] = *string;
138 break;
139 case 'r':
140 swap_arg = param[0];
141 param[0] = param[1];
142 param[1] = swap_arg;
143 break;
144 case 'i':
145 param[0] += 1;
146 param[1] += 1;
147 break;
148 case '>':
149 if (*value > string[1])
150 *value += string[2];
151 string += 2;
152 break;
153 case 'n': /* Datamedia 2500 */
154 param[0] ^= 0140;
155 param[1] ^= 0140;
156 break;
157 case 'B': /* BCD */
158 *value = 16 * (*value / 10) + (*value % 10);
159 break;
160 case 'D': /* Reverse coding (Delta Data) */
161 *value -= 2 * (*value % 16);
162 break;
163 }
164 if (fmt
15.1
'fmt' is equal to null
31.1
'fmt' is equal to null
!= 0) {
16
Taking false branch
32
Taking false branch
165 snprintf(result + used, length - used, fmt, *value++);
166 used += strlen(result + used);
167 fmt = 0;
168 }
169 if (value - param > 2) {
17
Taking false branch
33
Taking false branch
170 value = param + 2;
171 *value = 0;
172 }
173 } else {
174 result[used++] = *string;
175 }
176 string++;
177 }
178 if (result
35.1
'result' is not equal to null
!= 0) {
36
Taking true branch
179 if (need_BC
36.1
'need_BC' is true
) {
37
Taking true branch
180 copied = strlcpy(result + used, BC, length - used);
38
Null pointer passed as 2nd argument to string copy function
181 if (copied < length - used)
182 used += copied;
183 else
184 used += length - used - 1;
185 }
186 result[used] = '\0';
187 }
188 return result;
189}
190#endif
191
192/*
193 * Retained solely for upward compatibility. Note the intentional reversing of
194 * the last two arguments when invoking tparm().
195 */
196NCURSES_EXPORT(char *)char *
197tgoto(const char *string, int x, int y)
198{
199 char *result;
200
201 T((T_CALLED("tgoto(%s, %d, %d)"), _nc_visbuf(string), x, y));
202#if !PURE_TERMINFO0
203 if (is_termcap(string))
1
Taking true branch
204 result = tgoto_internal(string, x, y);
2
Calling 'tgoto_internal'
205 else
206#endif
207 result = TPARM_2((NCURSES_CONST char *) string, y, x)tparm((const char *) string,(long)(y),(long)(x));
208 returnPtr(result)return result;
209}