Bug Summary

File:libs/apr/network_io/unix/sockets.c
Location:line 39, column 15
Description:Access to field 'socketdes' results in a dereference of a null pointer (loaded from variable 'thesocket')

Annotated Source Code

1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr_arch_networkio.h"
18#include "apr_network_io.h"
19#include "apr_strings.h"
20#include "apr_support.h"
21#include "apr_portable.h"
22#include "apr_arch_inherit.h"
23
24#ifdef BEOS_R5
25#undef close
26#define close closesocket
27#endif /* BEOS_R5 */
28
29static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */
30
31static apr_status_t socket_cleanup(void *sock)
32{
33 apr_socket_t *thesocket = sock;
1
'thesocket' initialized here
34
35 if (thesocket && thesocket->socketdes == -1) {
2
Assuming pointer value is null
36 return APR_SUCCESS0;
37 }
38
39 if (close(thesocket->socketdes) == 0) {
3
Access to field 'socketdes' results in a dereference of a null pointer (loaded from variable 'thesocket')
40 thesocket->socketdes = -1;
41 return APR_SUCCESS0;
42 }
43 else {
44 return errno(*__errno_location ());
45 }
46}
47
48static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol)
49{
50 sock->type = type;
51 sock->protocol = protocol;
52 apr_sockaddr_vars_set(sock->local_addr, family, 0);
53 apr_sockaddr_vars_set(sock->remote_addr, family, 0);
54 sock->options = 0;
55#if defined(BEOS) && !defined(BEOS_BONE1)
56 /* BeOS pre-BONE has TCP_NODELAY on by default and it can't be
57 * switched off!
58 */
59 sock->options |= APR_TCP_NODELAY512;
60#endif
61}
62
63static void alloc_socket(apr_socket_t **new, apr_pool_t *p)
64{
65 *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t))memset(apr_palloc(p, sizeof(apr_socket_t)), 0, sizeof(apr_socket_t
))
;
66 (*new)->pool = p;
67 (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,memset(apr_palloc((*new)->pool, sizeof(apr_sockaddr_t)), 0
, sizeof(apr_sockaddr_t))
68 sizeof(apr_sockaddr_t))memset(apr_palloc((*new)->pool, sizeof(apr_sockaddr_t)), 0
, sizeof(apr_sockaddr_t))
;
69 (*new)->local_addr->pool = p;
70 (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,memset(apr_palloc((*new)->pool, sizeof(apr_sockaddr_t)), 0
, sizeof(apr_sockaddr_t))
71 sizeof(apr_sockaddr_t))memset(apr_palloc((*new)->pool, sizeof(apr_sockaddr_t)), 0
, sizeof(apr_sockaddr_t))
;
72 (*new)->remote_addr->pool = p;
73 (*new)->remote_addr_unknown = 1;
74#ifndef WAITIO_USES_POLL1
75 /* Create a pollset with room for one descriptor. */
76 /* ### check return codes */
77 (void) apr_pollset_create(&(*new)->pollset, 1, p, 0);
78#endif
79}
80
81apr_status_t apr_socket_protocol_get(apr_socket_t *sock, int *protocol)
82{
83 *protocol = sock->protocol;
84 return APR_SUCCESS0;
85}
86
87apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type,
88 int protocol, apr_pool_t *cont)
89{
90 int family = ofamily;
91
92 if (family == APR_UNSPEC0) {
93#if APR_HAVE_IPV61
94 family = APR_INET610;
95#else
96 family = APR_INET2;
97#endif
98 }
99
100 alloc_socket(new, cont);
101
102#ifndef BEOS_R5
103 (*new)->socketdes = socket(family, type, protocol);
104#else
105 /* For some reason BeOS R5 has an unconventional protocol numbering,
106 * so we need to translate here. */
107 switch (protocol) {
108 case 0:
109 (*new)->socketdes = socket(family, type, 0);
110 break;
111 case APR_PROTO_TCP6:
112 (*new)->socketdes = socket(family, type, IPPROTO_TCPIPPROTO_TCP);
113 break;
114 case APR_PROTO_UDP17:
115 (*new)->socketdes = socket(family, type, IPPROTO_UDPIPPROTO_UDP);
116 break;
117 case APR_PROTO_SCTP132:
118 default:
119 errno(*__errno_location ()) = EPROTONOSUPPORT93;
120 (*new)->socketdes = -1;
121 break;
122 }
123#endif /* BEOS_R5 */
124
125#if APR_HAVE_IPV61
126 if ((*new)->socketdes < 0 && ofamily == APR_UNSPEC0) {
127 family = APR_INET2;
128 (*new)->socketdes = socket(family, type, protocol);
129 }
130#endif
131
132 if ((*new)->socketdes < 0) {
133 return errno(*__errno_location ());
134 }
135 set_socket_vars(*new, family, type, protocol);
136
137 (*new)->timeout = -1;
138 (*new)->inherit = 0;
139 apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup,
140 socket_cleanup);
141
142 return APR_SUCCESS0;
143}
144
145apr_status_t apr_socket_shutdown(apr_socket_t *thesocket,
146 apr_shutdown_how_e how)
147{
148 return (shutdown(thesocket->socketdes, how) == -1) ? errno(*__errno_location ()) : APR_SUCCESS0;
149}
150
151apr_status_t apr_socket_close(apr_socket_t *thesocket)
152{
153 return apr_pool_cleanup_run(thesocket->pool, thesocket, socket_cleanup);
154}
155
156apr_status_t apr_socket_bind(apr_socket_t *sock, apr_sockaddr_t *sa)
157{
158 if (bind(sock->socketdes,
159 (struct sockaddr *)&sa->sa, sa->salen) == -1) {
160 return errno(*__errno_location ());
161 }
162 else {
163 sock->local_addr = sa;
164 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
165 if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */
166 sock->local_port_unknown = 1; /* kernel got us an ephemeral port */
167 }
168 return APR_SUCCESS0;
169 }
170}
171
172apr_status_t apr_socket_listen(apr_socket_t *sock, apr_int32_t backlog)
173{
174 if (listen(sock->socketdes, backlog) == -1)
175 return errno(*__errno_location ());
176 else
177 return APR_SUCCESS0;
178}
179
180apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock,
181 apr_pool_t *connection_context)
182{
183 alloc_socket(new, connection_context);
184 set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAMSOCK_STREAM, sock->protocol);
185
186#ifndef HAVE_POLL1
187 (*new)->connected = 1;
188#endif
189 (*new)->timeout = -1;
190
191 (*new)->socketdes = accept(sock->socketdes,
192 (struct sockaddr *)&(*new)->remote_addr->sa,
193 &(*new)->remote_addr->salen);
194
195 if ((*new)->socketdes < 0) {
196 return errno(*__errno_location ());
197 }
198#ifdef TPF
199 if ((*new)->socketdes == 0) {
200 /* 0 is an invalid socket for TPF */
201 return APR_EINTR4;
202 }
203#endif
204
205 (*new)->remote_addr_unknown = 0;
206
207 *(*new)->local_addr = *sock->local_addr;
208
209 /* The above assignment just overwrote the pool entry. Setting the local_addr
210 pool for the accepted socket back to what it should be. Otherwise all
211 allocations for this socket will come from a server pool that is not
212 freed until the process goes down.*/
213 (*new)->local_addr->pool = connection_context;
214
215 /* fix up any pointers which are no longer valid */
216 if (sock->local_addr->sa.sin.sin_family == AF_INET2) {
217 (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr;
218 }
219#if APR_HAVE_IPV61
220 else if (sock->local_addr->sa.sin.sin_family == AF_INET610) {
221 (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr;
222 }
223#endif
224 (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) ((*new)->remote_addr->sa.sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; }))
;
225 if (sock->local_port_unknown) {
226 /* not likely for a listening socket, but theoretically possible :) */
227 (*new)->local_port_unknown = 1;
228 }
229
230#if APR_TCP_NODELAY_INHERITED1
231 if (apr_is_option_set(sock, APR_TCP_NODELAY)(((sock)->options & (512)) == (512)) == 1) {
232 apr_set_option(*new, APR_TCP_NODELAY, 1)do { if (1) (*new)->options |= (512); else (*new)->options
&= ~(512); } while (0)
;
233 }
234#endif /* TCP_NODELAY_INHERITED */
235#if APR_O_NONBLOCK_INHERITED0
236 if (apr_is_option_set(sock, APR_SO_NONBLOCK)(((sock)->options & (8)) == (8)) == 1) {
237 apr_set_option(*new, APR_SO_NONBLOCK, 1)do { if (1) (*new)->options |= (8); else (*new)->options
&= ~(8); } while (0)
;
238 }
239#endif /* APR_O_NONBLOCK_INHERITED */
240
241 if (sock->local_interface_unknown ||
242 !memcmp(sock->local_addr->ipaddr_ptr,
243 generic_inaddr_any,
244 sock->local_addr->ipaddr_len)) {
245 /* If the interface address inside the listening socket's local_addr wasn't
246 * up-to-date, we don't know local interface of the connected socket either.
247 *
248 * If the listening socket was not bound to a specific interface, we
249 * don't know the local_addr of the connected socket.
250 */
251 (*new)->local_interface_unknown = 1;
252 }
253
254 (*new)->inherit = 0;
255 apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup,
256 socket_cleanup);
257 return APR_SUCCESS0;
258}
259
260apr_status_t apr_socket_connect(apr_socket_t *sock, apr_sockaddr_t *sa)
261{
262 int rc;
263
264 do {
265 rc = connect(sock->socketdes,
266 (const struct sockaddr *)&sa->sa.sin,
267 sa->salen);
268 } while (rc == -1 && errno(*__errno_location ()) == EINTR4);
269
270 /* we can see EINPROGRESS the first time connect is called on a non-blocking
271 * socket; if called again, we can see EALREADY
272 */
273 if ((rc == -1) && (errno(*__errno_location ()) == EINPROGRESS115 || errno(*__errno_location ()) == EALREADY114)
274 && (sock->timeout > 0)) {
275 rc = apr_wait_for_io_or_timeout(NULL((void*)0), sock, 0);
276 if (rc != APR_SUCCESS0) {
277 return rc;
278 }
279
280#ifdef SO_ERROR4
281 {
282 int error;
283 apr_socklen_t len = sizeof(error);
284 if ((rc = getsockopt(sock->socketdes, SOL_SOCKET1, SO_ERROR4,
285 (char *)&error, &len)) < 0) {
286 return errno(*__errno_location ());
287 }
288 if (error) {
289 return error;
290 }
291 }
292#endif /* SO_ERROR */
293 }
294
295 if (rc == -1 && errno(*__errno_location ()) != EISCONN106) {
296 return errno(*__errno_location ());
297 }
298
299 if (memcmp(sa->ipaddr_ptr, generic_inaddr_any, sa->ipaddr_len)) {
300 /* A real remote address was passed in. If the unspecified
301 * address was used, the actual remote addr will have to be
302 * determined using getpeername() if required. */
303 /* ### this should probably be a structure copy + fixup as per
304 * _accept()'s handling of local_addr */
305 sock->remote_addr = sa;
306 sock->remote_addr_unknown = 0;
307 }
308
309 if (sock->local_addr->port == 0) {
310 /* connect() got us an ephemeral port */
311 sock->local_port_unknown = 1;
312 }
313 if (!memcmp(sock->local_addr->ipaddr_ptr,
314 generic_inaddr_any,
315 sock->local_addr->ipaddr_len)) {
316 /* not bound to specific local interface; connect() had to assign
317 * one for the socket
318 */
319 sock->local_interface_unknown = 1;
320 }
321#ifndef HAVE_POLL1
322 sock->connected=1;
323#endif
324 return APR_SUCCESS0;
325}
326
327apr_status_t apr_socket_type_get(apr_socket_t *sock, int *type)
328{
329 *type = sock->type;
330 return APR_SUCCESS0;
331}
332
333apr_status_t apr_socket_data_get(void **data, const char *key, apr_socket_t *sock)
334{
335 sock_userdata_t *cur = sock->userdata;
336
337 *data = NULL((void*)0);
338
339 while (cur) {
340 if (!strcmp(cur->key, key)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(cur->key) && __builtin_constant_p (key) &&
(__s1_len = __builtin_strlen (cur->key), __s2_len = __builtin_strlen
(key), (!((size_t)(const void *)((cur->key) + 1) - (size_t
)(const void *)(cur->key) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((key) + 1) - (size_t)(const void *
)(key) == 1) || __s2_len >= 4)) ? __builtin_strcmp (cur->
key, key) : (__builtin_constant_p (cur->key) && ((
size_t)(const void *)((cur->key) + 1) - (size_t)(const void
*)(cur->key) == 1) && (__s1_len = __builtin_strlen
(cur->key), __s1_len < 4) ? (__builtin_constant_p (key
) && ((size_t)(const void *)((key) + 1) - (size_t)(const
void *)(key) == 1) ? __builtin_strcmp (cur->key, key) : (
__extension__ ({ const unsigned char *__s2 = (const unsigned char
*) (const char *) (key); int __result = (((const unsigned char
*) (const char *) (cur->key))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (cur->key))[1] - __s2[1]); if (__s1_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (cur->key))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (cur->key))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (key) && ((size_t)(const
void *)((key) + 1) - (size_t)(const void *)(key) == 1) &&
(__s2_len = __builtin_strlen (key), __s2_len < 4) ? (__builtin_constant_p
(cur->key) && ((size_t)(const void *)((cur->key
) + 1) - (size_t)(const void *)(cur->key) == 1) ? __builtin_strcmp
(cur->key, key) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (cur->key)
; int __result = (((const unsigned char *) (const char *) (key
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (key)
)[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (key)
)[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (key))[
3] - __s2[3]); } } __result; })))) : __builtin_strcmp (cur->
key, key)))); })
) {
341 *data = cur->data;
342 break;
343 }
344 cur = cur->next;
345 }
346
347 return APR_SUCCESS0;
348}
349
350apr_status_t apr_socket_data_set(apr_socket_t *sock, void *data, const char *key,
351 apr_status_t (*cleanup) (void *))
352{
353 sock_userdata_t *new = apr_palloc(sock->pool, sizeof(sock_userdata_t));
354
355 new->key = apr_pstrdup(sock->pool, key);
356 new->data = data;
357 new->next = sock->userdata;
358 sock->userdata = new;
359
360 if (cleanup) {
361 apr_pool_cleanup_register(sock->pool, data, cleanup, cleanup);
362 }
363
364 return APR_SUCCESS0;
365}
366
367apr_status_t apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock)
368{
369 *thesock = sock->socketdes;
370 return APR_SUCCESS0;
371}
372
373apr_status_t apr_os_sock_make(apr_socket_t **apr_sock,
374 apr_os_sock_info_t *os_sock_info,
375 apr_pool_t *cont)
376{
377 alloc_socket(apr_sock, cont);
378 set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol);
379 (*apr_sock)->timeout = -1;
380 (*apr_sock)->socketdes = *os_sock_info->os_sock;
381 if (os_sock_info->local) {
382 memcpy(&(*apr_sock)->local_addr->sa.sin,
383 os_sock_info->local,
384 (*apr_sock)->local_addr->salen);
385 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
386 (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) ((*apr_sock)->local_addr->sa.sin.sin_port); if (__builtin_constant_p
(__x)) __v = ((unsigned short int) ((((__x) >> 8) &
0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0"
: "=r" (__v) : "0" (__x) : "cc"); __v; }))
;
387 }
388 else {
389 (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1;
390 }
391 if (os_sock_info->remote) {
392#ifndef HAVE_POLL1
393 (*apr_sock)->connected = 1;
394#endif
395 memcpy(&(*apr_sock)->remote_addr->sa.sin,
396 os_sock_info->remote,
397 (*apr_sock)->remote_addr->salen);
398 /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
399 (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) ((*apr_sock)->remote_addr->sa.sin.sin_port); if (
__builtin_constant_p (__x)) __v = ((unsigned short int) ((((__x
) >> 8) & 0xff) | (((__x) & 0xff) << 8)))
; else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"
); __v; }))
;
400 }
401 else {
402 (*apr_sock)->remote_addr_unknown = 1;
403 }
404
405 (*apr_sock)->inherit = 0;
406 apr_pool_cleanup_register((*apr_sock)->pool, (void *)(*apr_sock),
407 socket_cleanup, socket_cleanup);
408 return APR_SUCCESS0;
409}
410
411apr_status_t apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock,
412 apr_pool_t *cont)
413{
414 /* XXX Bogus assumption that *sock points at anything legit */
415 if ((*sock) == NULL((void*)0)) {
416 alloc_socket(sock, cont);
417 /* XXX IPv6 figure out the family here! */
418 /* XXX figure out the actual socket type here */
419 /* *or* just decide that apr_os_sock_put() has to be told the family and type */
420 set_socket_vars(*sock, APR_INET2, SOCK_STREAMSOCK_STREAM, 0);
421 (*sock)->timeout = -1;
422 }
423 (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
424 (*sock)->remote_addr_unknown = 1;
425 (*sock)->socketdes = *thesock;
426 return APR_SUCCESS0;
427}
428
429APR_POOL_IMPLEMENT_ACCESSOR(socket)apr_pool_t * apr_socket_pool_get (const apr_socket_t *thesocket
) { return thesocket->pool; }
430
431APR_IMPLEMENT_INHERIT_SET(socket, inherit, pool, socket_cleanup)apr_status_t apr_socket_inherit_set(apr_socket_t *thesocket) {
if (thesocket->inherit & 0x00800) return 22; if (!(thesocket
->inherit & (1 << 24))) { thesocket->inherit |=
(1 << 24); apr_pool_child_cleanup_set(thesocket->pool
, (void *)thesocket, socket_cleanup, apr_pool_cleanup_null); }
return 0; }
432
433APR_IMPLEMENT_INHERIT_UNSET(socket, inherit, pool, socket_cleanup)apr_status_t apr_socket_inherit_unset(apr_socket_t *thesocket
) { if (thesocket->inherit & 0x00800) return 22; if (thesocket
->inherit & (1 << 24)) { thesocket->inherit &=
~(1 << 24); apr_pool_child_cleanup_set(thesocket->pool
, (void *)thesocket, socket_cleanup, socket_cleanup); } return
0; }