Bug Summary

File:out/../deps/openssl/openssl/crypto/http/http_lib.c
Warning:line 79, column 23
Although the value stored to 'host' is used in the enclosing expression, the value is never actually read from 'host'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name http_lib.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 2 -pic-is-pie -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 -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D OPENSSL_NO_HW -D OPENSSL_API_COMPAT=0x10100001L -D STATIC_LEGACY -D NDEBUG -D OPENSSL_USE_NODELETE -D L_ENDIAN -D OPENSSL_BUILDING_OPENSSL -D AES_ASM -D BSAES_ASM -D CMLL_ASM -D ECP_NISTZ256_ASM -D GHASH_ASM -D KECCAK1600_ASM -D MD5_ASM -D OPENSSL_BN_ASM_GF2m -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D OPENSSL_CPUID_OBJ -D OPENSSL_IA32_SSE2 -D PADLOCK_ASM -D POLY1305_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D VPAES_ASM -D WHIRLPOOL_ASM -D X25519_ASM -D OPENSSL_PIC -D MODULESDIR="/home/maurizio/node-v18.6.0/out/Release/obj.target/deps/openssl/lib/openssl-modules" -D OPENSSLDIR="/home/maurizio/node-v18.6.0/out/Release/obj.target/deps/openssl" -D OPENSSLDIR="/etc/ssl" -D ENGINESDIR="/dev/null" -D TERMIOS -I ../deps/openssl/openssl -I ../deps/openssl/openssl/include -I ../deps/openssl/openssl/crypto -I ../deps/openssl/openssl/crypto/include -I ../deps/openssl/openssl/crypto/modes -I ../deps/openssl/openssl/crypto/ec/curve448 -I ../deps/openssl/openssl/crypto/ec/curve448/arch_32 -I ../deps/openssl/openssl/providers/common/include -I ../deps/openssl/openssl/providers/implementations/include -I ../deps/openssl/config -I ../deps/openssl/config/archs/linux-x86_64/asm -I ../deps/openssl/config/archs/linux-x86_64/asm/include -I ../deps/openssl/config/archs/linux-x86_64/asm/crypto -I ../deps/openssl/config/archs/linux-x86_64/asm/crypto/include/internal -I ../deps/openssl/config/archs/linux-x86_64/asm/providers/common/include -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-missing-field-initializers -Wno-old-style-declaration -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c ../deps/openssl/openssl/crypto/http/http_lib.c
1/*
2 * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include <stdio.h> /* for sscanf() */
11#include <string.h>
12#include <openssl/http.h>
13#include <openssl/httperr.h>
14#include <openssl/bio.h> /* for BIO_snprintf() */
15#include <openssl/err.h>
16#include "internal/cryptlib.h" /* for ossl_assert() */
17
18static void init_pstring(char **pstr)
19{
20 if (pstr != NULL((void*)0)) {
21 *pstr = NULL((void*)0);
22 }
23}
24
25static int copy_substring(char **dest, const char *start, const char *end)
26{
27 return dest == NULL((void*)0)
28 || (*dest = OPENSSL_strndup(start, end - start)CRYPTO_strndup(start, end - start, "../deps/openssl/openssl/crypto/http/http_lib.c"
, 28)
) != NULL((void*)0);
29}
30
31static void free_pstring(char **pstr)
32{
33 if (pstr != NULL((void*)0)) {
34 OPENSSL_free(*pstr)CRYPTO_free(*pstr, "../deps/openssl/openssl/crypto/http/http_lib.c"
, 34)
;
35 *pstr = NULL((void*)0);
36 }
37}
38
39int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost,
40 char **pport, int *pport_num,
41 char **ppath, char **pquery, char **pfrag)
42{
43 const char *p, *tmp;
44 const char *scheme, *scheme_end;
45 const char *user, *user_end;
46 const char *host, *host_end;
47 const char *port, *port_end;
48 unsigned int portnum;
49 const char *path, *path_end;
50 const char *query, *query_end;
51 const char *frag, *frag_end;
52
53 init_pstring(pscheme);
54 init_pstring(puser);
55 init_pstring(phost);
56 init_pstring(pport);
57 init_pstring(ppath);
58 init_pstring(pfrag);
59 init_pstring(pquery);
60
61 if (url == NULL((void*)0)) {
62 ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/http/http_lib.c"
,62,__func__), ERR_set_error)((61),((258|((0x1 << 18L)|
(0x2 << 18L)))),((void*)0))
;
63 return 0;
64 }
65
66 /* check for optional prefix "<scheme>://" */
67 scheme = scheme_end = url;
68 p = strstr(url, "://");
69 if (p == NULL((void*)0)) {
70 p = url;
71 } else {
72 scheme_end = p;
73 if (scheme_end == scheme)
74 goto parse_err;
75 p += strlen("://");
76 }
77
78 /* parse optional "userinfo@" */
79 user = user_end = host = p;
Although the value stored to 'host' is used in the enclosing expression, the value is never actually read from 'host'
80 host = strchr(p, '@');
81 if (host != NULL((void*)0))
82 user_end = host++;
83 else
84 host = p;
85
86 /* parse host name/address as far as needed here */
87 if (host[0] == '[') {
88 /* ipv6 literal, which may include ':' */
89 host_end = strchr(host + 1, ']');
90 if (host_end == NULL((void*)0))
91 goto parse_err;
92 p = ++host_end;
93 } else {
94 /* look for start of optional port, path, query, or fragment */
95 host_end = strchr(host, ':');
96 if (host_end == NULL((void*)0))
97 host_end = strchr(host, '/');
98 if (host_end == NULL((void*)0))
99 host_end = strchr(host, '?');
100 if (host_end == NULL((void*)0))
101 host_end = strchr(host, '#');
102 if (host_end == NULL((void*)0)) /* the remaining string is just the hostname */
103 host_end = host + strlen(host);
104 p = host_end;
105 }
106
107 /* parse optional port specification starting with ':' */
108 port = "0"; /* default */
109 if (*p == ':')
110 port = ++p;
111 /* remaining port spec handling is also done for the default values */
112 /* make sure a decimal port number is given */
113 if (!sscanf(port, "%u", &portnum) || portnum > 65535) {
114 ERR_raise_data(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/http/http_lib.c"
,114,__func__), ERR_set_error)
(ERR_LIB_HTTP61, HTTP_R_INVALID_PORT_NUMBER123, "%s", port);
115 goto err;
116 }
117 for (port_end = port; '0' <= *port_end && *port_end <= '9'; port_end++)
118 ;
119 if (port == p) /* port was given explicitly */
120 p += port_end - port;
121
122 /* check for optional path starting with '/' or '?'. Else must start '#' */
123 path = p;
124 if (*path != '\0' && *path != '/' && *path != '?' && *path != '#') {
125 ERR_raise(ERR_LIB_HTTP, HTTP_R_INVALID_URL_PATH)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/http/http_lib.c"
,125,__func__), ERR_set_error)((61),(125),((void*)0))
;
126 goto parse_err;
127 }
128 path_end = query = query_end = frag = frag_end = path + strlen(path);
129
130 /* parse optional "?query" */
131 tmp = strchr(p, '?');
132 if (tmp != NULL((void*)0)) {
133 p = tmp;
134 if (pquery != NULL((void*)0)) {
135 path_end = p;
136 query = p + 1;
137 }
138 }
139
140 /* parse optional "#fragment" */
141 tmp = strchr(p, '#');
142 if (tmp != NULL((void*)0)) {
143 if (query == path_end) /* we did not record a query component */
144 path_end = tmp;
145 query_end = tmp;
146 frag = tmp + 1;
147 }
148
149 if (!copy_substring(pscheme, scheme, scheme_end)
150 || !copy_substring(phost, host, host_end)
151 || !copy_substring(pport, port, port_end)
152 || !copy_substring(puser, user, user_end)
153 || !copy_substring(pquery, query, query_end)
154 || !copy_substring(pfrag, frag, frag_end))
155 goto err;
156 if (pport_num != NULL((void*)0))
157 *pport_num = (int)portnum;
158 if (*path == '/') {
159 if (!copy_substring(ppath, path, path_end))
160 goto err;
161 } else if (ppath != NULL((void*)0)) { /* must prepend '/' */
162 size_t buflen = 1 + path_end - path + 1;
163
164 if ((*ppath = OPENSSL_malloc(buflen)CRYPTO_malloc(buflen, "../deps/openssl/openssl/crypto/http/http_lib.c"
, 164)
) == NULL((void*)0))
165 goto err;
166 BIO_snprintf(*ppath, buflen, "/%s", path);
167 }
168 return 1;
169
170 parse_err:
171 ERR_raise(ERR_LIB_HTTP, HTTP_R_ERROR_PARSING_URL)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/http/http_lib.c"
,171,__func__), ERR_set_error)((61),(101),((void*)0))
;
172
173 err:
174 free_pstring(pscheme);
175 free_pstring(puser);
176 free_pstring(phost);
177 free_pstring(pport);
178 free_pstring(ppath);
179 free_pstring(pquery);
180 free_pstring(pfrag);
181 return 0;
182}
183
184int OSSL_HTTP_parse_url(const char *url, int *pssl, char **puser, char **phost,
185 char **pport, int *pport_num,
186 char **ppath, char **pquery, char **pfrag)
187{
188 char *scheme, *port;
189 int ssl = 0, portnum;
190
191 init_pstring(pport);
192 if (pssl != NULL((void*)0))
193 *pssl = 0;
194 if (!OSSL_parse_url(url, &scheme, puser, phost, &port, pport_num,
195 ppath, pquery, pfrag))
196 return 0;
197
198 /* check for optional HTTP scheme "http[s]" */
199 if (strcmp(scheme, OSSL_HTTPS_NAME"https") == 0) {
200 ssl = 1;
201 if (pssl != NULL((void*)0))
202 *pssl = ssl;
203 } else if (*scheme != '\0' && strcmp(scheme, OSSL_HTTP_NAME"http") != 0) {
204 ERR_raise(ERR_LIB_HTTP, HTTP_R_INVALID_URL_SCHEME)(ERR_new(), ERR_set_debug("../deps/openssl/openssl/crypto/http/http_lib.c"
,204,__func__), ERR_set_error)((61),(124),((void*)0))
;
205 OPENSSL_free(scheme)CRYPTO_free(scheme, "../deps/openssl/openssl/crypto/http/http_lib.c"
, 205)
;
206 OPENSSL_free(port)CRYPTO_free(port, "../deps/openssl/openssl/crypto/http/http_lib.c"
, 206)
;
207 goto err;
208 }
209 OPENSSL_free(scheme)CRYPTO_free(scheme, "../deps/openssl/openssl/crypto/http/http_lib.c"
, 209)
;
210
211 if (strcmp(port, "0") == 0) {
212 /* set default port */
213 OPENSSL_free(port)CRYPTO_free(port, "../deps/openssl/openssl/crypto/http/http_lib.c"
, 213)
;
214 port = ssl ? OSSL_HTTPS_PORT"443" : OSSL_HTTP_PORT"80";
215 if (!ossl_assert(sscanf(port, "%d", &portnum) == 1)((sscanf(port, "%d", &portnum) == 1) != 0))
216 goto err;
217 if (pport_num != NULL((void*)0))
218 *pport_num = portnum;
219 if (pport != NULL((void*)0)) {
220 *pport = OPENSSL_strdup(port)CRYPTO_strdup(port, "../deps/openssl/openssl/crypto/http/http_lib.c"
, 220)
;
221 if (*pport == NULL((void*)0))
222 goto err;
223 }
224 } else {
225 if (pport != NULL((void*)0))
226 *pport = port;
227 else
228 OPENSSL_free(port)CRYPTO_free(port, "../deps/openssl/openssl/crypto/http/http_lib.c"
, 228)
;
229 }
230 return 1;
231
232 err:
233 free_pstring(puser);
234 free_pstring(phost);
235 free_pstring(ppath);
236 free_pstring(pquery);
237 free_pstring(pfrag);
238 return 0;
239}
240
241/* Respect no_proxy, taking default value from environment variable(s) */
242static int use_proxy(const char *no_proxy, const char *server)
243{
244 size_t sl;
245 const char *found = NULL((void*)0);
246
247 if (!ossl_assert(server != NULL)((server != ((void*)0)) != 0))
248 return 0;
249 sl = strlen(server);
250
251 /*
252 * using environment variable names, both lowercase and uppercase variants,
253 * compatible with other HTTP client implementations like wget, curl and git
254 */
255 if (no_proxy == NULL((void*)0))
256 no_proxy = getenv("no_proxy");
257 if (no_proxy == NULL((void*)0))
258 no_proxy = getenv(OPENSSL_NO_PROXY"NO_PROXY");
259
260 if (no_proxy != NULL((void*)0))
261 found = strstr(no_proxy, server);
262 while (found != NULL((void*)0)
263 && ((found != no_proxy && found[-1] != ' ' && found[-1] != ',')
264 || (found[sl] != '\0' && found[sl] != ' ' && found[sl] != ',')))
265 found = strstr(found + 1, server);
266 return found == NULL((void*)0);
267}
268
269/* Take default value from environment variable(s), respect no_proxy */
270const char *OSSL_HTTP_adapt_proxy(const char *proxy, const char *no_proxy,
271 const char *server, int use_ssl)
272{
273 /*
274 * using environment variable names, both lowercase and uppercase variants,
275 * compatible with other HTTP client implementations like wget, curl and git
276 */
277 if (proxy == NULL((void*)0))
278 proxy = getenv(use_ssl ? "https_proxy" : "http_proxy");
279 if (proxy == NULL((void*)0))
280 proxy = getenv(use_ssl ? OPENSSL_HTTP_PROXY"HTTP_PROXY" :
281 OPENSSL_HTTPS_PROXY"HTTPS_PROXY");
282
283 if (proxy == NULL((void*)0) || *proxy == '\0' || !use_proxy(no_proxy, server))
284 return NULL((void*)0);
285 return proxy;
286}