Bug Summary

File:src/lib/libcurses/tinfo/lib_tgoto.c
Warning:line 188, column 6
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.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name lib_tgoto.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 -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -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/llvm16/lib/clang/16 -I . -I /usr/src/lib/libcurses -D _XOPEN_SOURCE_EXTENDED -D NDEBUG -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcurses/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -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/scan/2024-01-11-140451-98009-1 -x c /usr/src/lib/libcurses/tinfo/lib_tgoto.c
1/* $OpenBSD: lib_tgoto.c,v 1.7 2023/10/17 09:52:09 nicm Exp $ */
2
3/****************************************************************************
4 * Copyright 2018-2020,2023 Thomas E. Dickey *
5 * Copyright 2000-2008,2012 Free Software Foundation, Inc. *
6 * *
7 * Permission is hereby granted, free of charge, to any person obtaining a *
8 * copy of this software and associated documentation files (the *
9 * "Software"), to deal in the Software without restriction, including *
10 * without limitation the rights to use, copy, modify, merge, publish, *
11 * distribute, distribute with modifications, sublicense, and/or sell *
12 * copies of the Software, and to permit persons to whom the Software is *
13 * furnished to do so, subject to the following conditions: *
14 * *
15 * The above copyright notice and this permission notice shall be included *
16 * in all copies or substantial portions of the Software. *
17 * *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
21 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
24 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
25 * *
26 * Except as contained in this notice, the name(s) of the above copyright *
27 * holders shall not be used in advertising or otherwise to promote the *
28 * sale, use or other dealings in this Software without prior written *
29 * authorization. *
30 ****************************************************************************/
31
32/****************************************************************************
33 * Author: Thomas E. Dickey *
34 ****************************************************************************/
35
36#include <curses.priv.h>
37
38#include <ctype.h>
39#include <termcap.h>
40
41MODULE_ID("$Id: lib_tgoto.c,v 1.7 2023/10/17 09:52:09 nicm Exp $")
42
43#if !PURE_TERMINFO0
44static bool_Bool
45is_termcap(const char *string)
46{
47 bool_Bool result = TRUE1;
48
49 if (string == 0 || *string == '\0') {
50 result = FALSE0; /* tparm() handles empty strings */
51 } else {
52 while ((*string != '\0') && result) {
53 if (*string == '%') {
54 switch (*++string) {
55 case 'p':
56 result = FALSE0;
57 break;
58 case '\0':
59 string--;
60 break;
61 }
62 } else if (string[0] == '$' && string[1] == '<') {
63 result = FALSE0;
64 }
65 string++;
66 }
67 }
68 return result;
69}
70
71static char *
72tgoto_internal(const char *string, int x, int y)
73{
74 static char *result;
75 static size_t length;
76
77 int swap_arg;
78 int param[3];
79 size_t used = 0;
80 size_t need = 10;
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 186
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, (size_t)(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 /* tputs will pretend this is \0, which will almost
132 * always work since ANSI-compatible terminals ignore
133 * the character. ECMA-48 does not document a C1
134 * control for this value. A few (obsolete) terminals
135 * can use this value in special cases, such as cursor
136 * addressing using single-byte coordinates.
137 */
138 *value = 0200;
139 }
140 }
141 result[used++] = (char) *value++;
142 break;
143 case '%':
144 result[used++] = *string;
145 break;
146 case 'r':
147 swap_arg = param[0];
148 param[0] = param[1];
149 param[1] = swap_arg;
150 break;
151 case 'i':
152 param[0] += 1;
153 param[1] += 1;
154 break;
155 case '>':
156 if (*value > string[1])
157 *value += string[2];
158 string += 2;
159 break;
160 case 'n': /* Datamedia 2500 */
161 param[0] ^= 0140;
162 param[1] ^= 0140;
163 break;
164 case 'B': /* BCD */
165 *value = 16 * (*value / 10) + (*value % 10);
166 break;
167 case 'D': /* Reverse coding (Delta Data) */
168 *value -= 2 * (*value % 16);
169 break;
170 }
171 if (fmt
15.1
'fmt' is equal to null
31.1
'fmt' is equal to null
!= 0) {
15
Execution continues on line 171
16
Taking false branch
31
Execution continues on line 171
32
Taking false branch
172 _nc_SPRINTF(void) (snprintf)(result + used, _nc_SLIMIT(length - used)(size_t)(length - used),
173 fmt, *value++);
174 used += strlen(result + used);
175 fmt = 0;
176 }
177 if (value - param > 2) {
17
Taking false branch
33
Taking false branch
178 value = param + 2;
179 *value = 0;
180 }
181 } else {
182 result[used++] = *string;
183 }
184 string++;
185 }
186 if (result
35.1
'result' is not equal to null
!= 0) {
36
Taking true branch
187 if (need_BC
36.1
'need_BC' is true
) {
37
Taking true branch
188 _nc_STRCPY(result + used, BC, length - used)(void) strlcpy((result + used),(BC),(size_t)(length - used));
38
Null pointer passed as 2nd argument to string copy function
189 used += strlen(BC);
190 }
191 result[used] = '\0';
192 }
193 return result;
194}
195#endif
196
197/*
198 * Retained solely for upward compatibility. Note the intentional reversing of
199 * the last two arguments when invoking tparm().
200 */
201NCURSES_EXPORT(char *)char *
202tgoto(const char *string, int x, int y)
203{
204 char *result;
205
206 T((T_CALLED("tgoto(%s, %d, %d)"), _nc_visbuf(string), x, y));
207#if !PURE_TERMINFO0
208 if (is_termcap(string))
1
Taking true branch
209 result = tgoto_internal(string, x, y);
2
Calling 'tgoto_internal'
210 else
211#endif
212 if ((result = TIPARM_2(string, y, x)_nc_tiparm(2,string,y,x)) == NULL((void *)0)) {
213 /*
214 * Because termcap did not provide a more general solution such as
215 * tparm(), it was necessary to handle single-parameter capabilities
216 * using tgoto(). The internal _nc_tiparm() function returns a NULL
217 * for that case; retry for the single-parameter case.
218 */
219 if ((result = TIPARM_1(string, y)_nc_tiparm(1,string,y)) == NULL((void *)0)) {
220 result = TIPARM_0(string)_nc_tiparm(0,string);
221 }
222 }
223 returnPtr(result)return result;
224}