Bug Summary

File:src/lib/libcrypto/asn1/a_string.c
Warning:line 428, column 16
Array access (from variable 's') results in a null pointer dereference

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 a_string.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/libcrypto/obj -resource-dir /usr/local/llvm16/lib/clang/16 -D LIBRESSL_INTERNAL -D HAVE_FUNOPEN -I /usr/src/lib/libcrypto -I /usr/src/lib/libcrypto/arch/amd64 -I /usr/src/lib/libcrypto/asn1 -I /usr/src/lib/libcrypto/bio -I /usr/src/lib/libcrypto/bn -I /usr/src/lib/libcrypto/bn/arch/amd64 -I /usr/src/lib/libcrypto/bytestring -I /usr/src/lib/libcrypto/curve25519 -I /usr/src/lib/libcrypto/dh -I /usr/src/lib/libcrypto/dsa -I /usr/src/lib/libcrypto/ec -I /usr/src/lib/libcrypto/ecdsa -I /usr/src/lib/libcrypto/evp -I /usr/src/lib/libcrypto/hidden -I /usr/src/lib/libcrypto/hmac -I /usr/src/lib/libcrypto/kdf -I /usr/src/lib/libcrypto/modes -I /usr/src/lib/libcrypto/ocsp -I /usr/src/lib/libcrypto/pkcs12 -I /usr/src/lib/libcrypto/rsa -I /usr/src/lib/libcrypto/sha -I /usr/src/lib/libcrypto/ts -I /usr/src/lib/libcrypto/x509 -I /usr/src/lib/libcrypto/obj -D AES_ASM -D BSAES_ASM -D VPAES_ASM -D OPENSSL_IA32_SSE2 -D RSA_ASM -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D MD5_ASM -D GHASH_ASM -D RC4_MD5_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D WHIRLPOOL_ASM -D OPENSSL_CPUID_OBJ -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcrypto/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/libcrypto/asn1/a_string.c
1/* $OpenBSD: a_string.c,v 1.17 2023/08/15 18:05:15 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <limits.h>
60#include <stdlib.h>
61#include <string.h>
62
63#include <openssl/asn1.h>
64#include <openssl/err.h>
65
66#include "asn1_local.h"
67
68ASN1_STRING *
69ASN1_STRING_new(void)
70{
71 return ASN1_STRING_type_new(V_ASN1_OCTET_STRING4);
72}
73LCRYPTO_ALIAS(ASN1_STRING_new)asm("");
74
75ASN1_STRING *
76ASN1_STRING_type_new(int type)
77{
78 ASN1_STRING *astr;
79
80 if ((astr = calloc(1, sizeof(ASN1_STRING))) == NULL((void *)0)) {
81 ASN1error(ERR_R_MALLOC_FAILURE)ERR_put_error(13,(0xfff),((1|64)),"/usr/src/lib/libcrypto/asn1/a_string.c"
,81)
;
82 return NULL((void *)0);
83 }
84 astr->type = type;
85
86 return astr;
87}
88LCRYPTO_ALIAS(ASN1_STRING_type_new)asm("");
89
90static void
91ASN1_STRING_clear(ASN1_STRING *astr)
92{
93 if (!(astr->flags & ASN1_STRING_FLAG_NDEF0x010))
94 freezero(astr->data, astr->length);
95
96 astr->flags &= ~ASN1_STRING_FLAG_NDEF0x010;
97 astr->data = NULL((void *)0);
98 astr->length = 0;
99}
100
101void
102ASN1_STRING_free(ASN1_STRING *astr)
103{
104 if (astr == NULL((void *)0))
105 return;
106
107 ASN1_STRING_clear(astr);
108
109 free(astr);
110}
111LCRYPTO_ALIAS(ASN1_STRING_free)asm("");
112
113int
114ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
115{
116 int cmp;
117
118 if (a == NULL((void *)0) || b == NULL((void *)0))
119 return -1;
120 if ((cmp = (a->length - b->length)) != 0)
121 return cmp;
122 if (a->length != 0) {
123 if ((cmp = memcmp(a->data, b->data, a->length)) != 0)
124 return cmp;
125 }
126
127 return a->type - b->type;
128}
129LCRYPTO_ALIAS(ASN1_STRING_cmp)asm("");
130
131int
132ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *src)
133{
134 if (src == NULL((void *)0))
135 return 0;
136
137 if (!ASN1_STRING_set(dst, src->data, src->length))
138 return 0;
139
140 dst->type = src->type;
141 dst->flags = src->flags & ~ASN1_STRING_FLAG_NDEF0x010;
142
143 return 1;
144}
145LCRYPTO_ALIAS(ASN1_STRING_copy)asm("");
146
147ASN1_STRING *
148ASN1_STRING_dup(const ASN1_STRING *src)
149{
150 ASN1_STRING *astr;
151
152 if (src == NULL((void *)0))
153 return NULL((void *)0);
154
155 if ((astr = ASN1_STRING_new()) == NULL((void *)0))
156 return NULL((void *)0);
157 if (!ASN1_STRING_copy(astr, src)) {
158 ASN1_STRING_free(astr);
159 return NULL((void *)0);
160 }
161 return astr;
162}
163LCRYPTO_ALIAS(ASN1_STRING_dup)asm("");
164
165int
166ASN1_STRING_set(ASN1_STRING *astr, const void *_data, int len)
167{
168 const char *data = _data;
169
170 if (len == -1) {
171 size_t slen;
172
173 if (data == NULL((void *)0))
174 return 0;
175
176 if ((slen = strlen(data)) > INT_MAX0x7fffffff)
177 return 0;
178
179 len = (int)slen;
180 }
181
182 ASN1_STRING_clear(astr);
183
184 if (len < 0 || len >= INT_MAX0x7fffffff)
185 return 0;
186
187 if ((astr->data = calloc(1, len + 1)) == NULL((void *)0)) {
188 ASN1error(ERR_R_MALLOC_FAILURE)ERR_put_error(13,(0xfff),((1|64)),"/usr/src/lib/libcrypto/asn1/a_string.c"
,188)
;
189 return 0;
190 }
191 astr->length = len;
192
193 if (data != NULL((void *)0)) {
194 memcpy(astr->data, data, len);
195 astr->data[len] = '\0';
196 }
197
198 return 1;
199}
200LCRYPTO_ALIAS(ASN1_STRING_set)asm("");
201
202void
203ASN1_STRING_set0(ASN1_STRING *astr, void *data, int len)
204{
205 ASN1_STRING_clear(astr);
206
207 astr->data = data;
208 astr->length = len;
209}
210LCRYPTO_ALIAS(ASN1_STRING_set0)asm("");
211
212int
213ASN1_STRING_length(const ASN1_STRING *astr)
214{
215 return astr->length;
216}
217LCRYPTO_ALIAS(ASN1_STRING_length)asm("");
218
219void
220ASN1_STRING_length_set(ASN1_STRING *astr, int len)
221{
222 /* This is dangerous and unfixable. */
223 astr->length = len;
224}
225LCRYPTO_ALIAS(ASN1_STRING_length_set)asm("");
226
227int
228ASN1_STRING_type(const ASN1_STRING *astr)
229{
230 return astr->type;
231}
232LCRYPTO_ALIAS(ASN1_STRING_type)asm("");
233
234unsigned char *
235ASN1_STRING_data(ASN1_STRING *astr)
236{
237 return astr->data;
238}
239LCRYPTO_ALIAS(ASN1_STRING_data)asm("");
240
241const unsigned char *
242ASN1_STRING_get0_data(const ASN1_STRING *astr)
243{
244 return astr->data;
245}
246LCRYPTO_ALIAS(ASN1_STRING_get0_data)asm("");
247
248int
249ASN1_STRING_print(BIO *bp, const ASN1_STRING *astr)
250{
251 int i, n;
252 char buf[80];
253 const char *p;
254
255 if (astr == NULL((void *)0))
256 return 0;
257
258 n = 0;
259 p = (const char *)astr->data;
260 for (i = 0; i < astr->length; i++) {
261 if ((p[i] > '~') || ((p[i] < ' ') &&
262 (p[i] != '\n') && (p[i] != '\r')))
263 buf[n] = '.';
264 else
265 buf[n] = p[i];
266 n++;
267 if (n >= 80) {
268 if (BIO_write(bp, buf, n) <= 0)
269 return 0;
270 n = 0;
271 }
272 }
273 if (n > 0) {
274 if (BIO_write(bp, buf, n) <= 0)
275 return 0;
276 }
277
278 return 1;
279}
280LCRYPTO_ALIAS(ASN1_STRING_print)asm("");
281
282/*
283 * Utility function: convert any string type to UTF8, returns number of bytes
284 * in output string or a negative error code
285 */
286int
287ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in)
288{
289 ASN1_STRING *astr = NULL((void *)0);
290 int mbflag;
291 int ret = -1;
292
293 /*
294 * XXX We can't fail on *out != NULL here since things like haproxy and
295 * grpc pass in a pointer to an uninitialized pointer on the stack.
296 */
297 if (out == NULL((void *)0))
298 goto err;
299
300 if (in == NULL((void *)0))
301 goto err;
302
303 if ((mbflag = asn1_tag2charwidth(in->type)) == -1)
304 goto err;
305
306 mbflag |= MBSTRING_FLAG0x1000;
307
308 if ((ret = ASN1_mbstring_copy(&astr, in->data, in->length, mbflag,
309 B_ASN1_UTF8STRING0x2000)) < 0)
310 goto err;
311
312 *out = astr->data;
313 ret = astr->length;
314
315 astr->data = NULL((void *)0);
316 astr->length = 0;
317
318 err:
319 ASN1_STRING_free(astr);
320
321 return ret;
322}
323LCRYPTO_ALIAS(ASN1_STRING_to_UTF8)asm("");
324
325int
326i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *astr, int type)
327{
328 int i, n = 0;
329 static const char h[] = "0123456789ABCDEF";
330 char buf[2];
331
332 if (astr == NULL((void *)0))
333 return 0;
334
335 if (astr->length == 0) {
336 if (BIO_write(bp, "0", 1) != 1)
337 goto err;
338 n = 1;
339 } else {
340 for (i = 0; i < astr->length; i++) {
341 if ((i != 0) && (i % 35 == 0)) {
342 if (BIO_write(bp, "\\\n", 2) != 2)
343 goto err;
344 n += 2;
345 }
346 buf[0] = h[((unsigned char)astr->data[i] >> 4) & 0x0f];
347 buf[1] = h[((unsigned char)astr->data[i]) & 0x0f];
348 if (BIO_write(bp, buf, 2) != 2)
349 goto err;
350 n += 2;
351 }
352 }
353 return n;
354
355 err:
356 return -1;
357}
358LCRYPTO_ALIAS(i2a_ASN1_STRING)asm("");
359
360int
361a2i_ASN1_STRING(BIO *bp, ASN1_STRING *astr, char *buf, int size)
362{
363 int ret = 0;
364 int i, j, k, m, n, again, bufsize;
365 unsigned char *s = NULL((void *)0), *sp;
1
's' initialized to a null pointer value
366 unsigned char *bufp;
367 int first = 1;
368 size_t num = 0, slen = 0;
369
370 bufsize = BIO_gets(bp, buf, size);
371 for (;;) {
2
Loop condition is true. Entering loop body
21
Loop condition is true. Entering loop body
372 if (bufsize < 1) {
3
Assuming 'bufsize' is >= 1
4
Taking false branch
22
Assuming 'bufsize' is >= 1
23
Taking false branch
373 if (first)
374 break;
375 else
376 goto err_sl;
377 }
378 first = 0;
379
380 i = bufsize;
381 if (buf[i-1] == '\n')
5
Assuming the condition is false
6
Taking false branch
24
Assuming the condition is false
25
Taking false branch
382 buf[--i] = '\0';
383 if (i
6.1
'i' is not equal to 0
25.1
'i' is not equal to 0
== 0)
7
Taking false branch
26
Taking false branch
384 goto err_sl;
385 if (buf[i-1] == '\r')
8
Assuming the condition is false
9
Taking false branch
27
Assuming the condition is false
28
Taking false branch
386 buf[--i] = '\0';
387 if (i
9.1
'i' is not equal to 0
28.1
'i' is not equal to 0
== 0)
10
Taking false branch
29
Taking false branch
388 goto err_sl;
389 if (buf[i - 1] == '\\') {
11
Assuming the condition is true
12
Taking true branch
30
Assuming the condition is false
31
Taking false branch
390 i--;
391 again = 1;
392 } else
393 again = 0;
394 buf[i] = '\0';
395 if (i < 2)
13
Assuming 'i' is >= 2
14
Taking false branch
32
Assuming 'i' is >= 2
33
Taking false branch
396 goto err_sl;
397
398 bufp = (unsigned char *)buf;
399
400 k = 0;
401 if (i % 2 != 0) {
15
Assuming the condition is false
16
Taking false branch
34
Assuming the condition is false
35
Taking false branch
402 ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS)ERR_put_error(13,(0xfff),(145),"/usr/src/lib/libcrypto/asn1/a_string.c"
,402)
;
403 goto err;
404 }
405 i /= 2;
406 if (num + i > slen) {
17
Assuming the condition is false
18
Taking false branch
36
Assuming the condition is false
37
Taking false branch
407 sp = realloc(s, num + i);
408 if (sp == NULL((void *)0)) {
409 ASN1error(ERR_R_MALLOC_FAILURE)ERR_put_error(13,(0xfff),((1|64)),"/usr/src/lib/libcrypto/asn1/a_string.c"
,409)
;
410 goto err;
411 }
412 s = sp;
413 slen = num + i;
414 }
415 for (j = 0; j
18.1
'j' is >= 'i'
< i
; j++, k += 2) {
19
Loop condition is false. Execution continues on line 432
38
Assuming 'j' is < 'i'
39
Loop condition is true. Entering loop body
416 for (n = 0; n < 2; n++) {
40
Loop condition is true. Entering loop body
417 m = bufp[k + n];
418 if ((m >= '0') && (m <= '9'))
41
Assuming the condition is true
42
Assuming the condition is true
43
Taking true branch
419 m -= '0';
420 else if ((m >= 'a') && (m <= 'f'))
421 m = m - 'a' + 10;
422 else if ((m >= 'A') && (m <= 'F'))
423 m = m - 'A' + 10;
424 else {
425 ASN1error(ASN1_R_NON_HEX_CHARACTERS)ERR_put_error(13,(0xfff),(141),"/usr/src/lib/libcrypto/asn1/a_string.c"
,425)
;
426 goto err;
427 }
428 s[num + j] <<= 4;
44
Array access (from variable 's') results in a null pointer dereference
429 s[num + j] |= m;
430 }
431 }
432 num += i;
433 if (again
19.1
'again' is 1
)
20
Taking true branch
434 bufsize = BIO_gets(bp, buf, size);
435 else
436 break;
437 }
438 astr->length = num;
439 astr->data = s;
440
441 return 1;
442
443 err_sl:
444 ASN1error(ASN1_R_SHORT_LINE)ERR_put_error(13,(0xfff),(150),"/usr/src/lib/libcrypto/asn1/a_string.c"
,444)
;
445 err:
446 free(s);
447
448 return ret;
449}
450LCRYPTO_ALIAS(a2i_ASN1_STRING)asm("");