Coverage Report

Created: 2026-07-16 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl/lib/curlx/inet_pton.c
Line
Count
Source
1
/* This is from the BIND 4.9.4 release, modified to compile by itself */
2
3
/* Copyright (c) Internet Software Consortium.
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
10
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
12
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16
 * SOFTWARE.
17
 *
18
 * SPDX-License-Identifier: ISC
19
 */
20
#include "curl_setup.h"
21
22
#ifdef HAVE_SYS_PARAM_H
23
#include <sys/param.h>
24
#endif
25
#ifdef HAVE_NETINET_IN_H
26
#include <netinet/in.h>
27
#endif
28
#ifdef HAVE_ARPA_INET_H
29
#include <arpa/inet.h>
30
#endif
31
32
#include "curlx/inet_pton.h"
33
#include "curlx/strparse.h"
34
35
660
#define IN6ADDRSZ       16
36
65
#define INADDRSZ         4
37
486
#define INT16SZ          2
38
39
/*
40
 * If USE_IPV6 is disabled, we still want to parse IPv6 addresses, so make
41
 * sure we have _some_ value for AF_INET6 without polluting our fake value
42
 * everywhere.
43
 */
44
#if !defined(USE_IPV6) && !defined(AF_INET6)
45
#define AF_INET6 (AF_INET + 1)
46
#endif
47
48
/*
49
 * WARNING: Do not even consider trying to compile this on a system where
50
 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
51
 */
52
53
/* int inet_pton4(src, dst)
54
 *      like inet_aton() but without all the hexadecimal and shorthand.
55
 * return:
56
 *      1 if `src' is a valid dotted quad, else 0.
57
 * notice:
58
 *      does not touch `dst' unless it is returning 1.
59
 * author:
60
 *      Paul Vixie, 1996.
61
 */
62
static int inet_pton4(const char *src, unsigned char *dst)
63
58
{
64
58
  int saw_digit, octets, ch;
65
58
  unsigned char tmp[INADDRSZ], *tp;
66
67
58
  saw_digit = 0;
68
58
  octets = 0;
69
58
  tp = tmp;
70
58
  *tp = 0;
71
244
  while((ch = (unsigned char)*src++) != '\0') {
72
215
    if(ISDIGIT(ch)) {
73
143
      unsigned int val = (*tp * 10) + (ch - '0');
74
75
143
      if(saw_digit && *tp == 0)
76
1
        return 0;
77
142
      if(val > 255)
78
9
        return 0;
79
133
      *tp = (unsigned char)val;
80
133
      if(!saw_digit) {
81
74
        if(++octets > 4)
82
0
          return 0;
83
74
        saw_digit = 1;
84
74
      }
85
133
    }
86
72
    else if(ch == '.' && saw_digit) {
87
54
      if(octets == 4)
88
1
        return 0;
89
53
      *++tp = 0;
90
53
      saw_digit = 0;
91
53
    }
92
18
    else
93
18
      return 0;
94
215
  }
95
29
  if(octets < 4)
96
26
    return 0;
97
3
  memcpy(dst, tmp, INADDRSZ);
98
3
  return 1;
99
29
}
100
101
/* int inet_pton6(src, dst)
102
 *      convert presentation level address to network order binary form.
103
 * return:
104
 *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
105
 * notice:
106
 *      (1) does not touch `dst' unless it is returning 1.
107
 *      (2) :: in a full address is silently ignored.
108
 * credit:
109
 *      inspired by Mark Andrews.
110
 * author:
111
 *      Paul Vixie, 1996.
112
 */
113
static int inet_pton6(const char *src, unsigned char *dst)
114
274
{
115
274
  unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
116
274
  const char *curtok;
117
274
  int ch, saw_xdigit;
118
274
  size_t val;
119
120
274
  memset((tp = tmp), 0, IN6ADDRSZ);
121
274
  endp = tp + IN6ADDRSZ;
122
274
  colonp = NULL;
123
  /* Leading :: requires some special handling. */
124
274
  if(*src == ':')
125
75
    if(*++src != ':')
126
10
      return 0;
127
264
  curtok = src;
128
264
  saw_xdigit = 0;
129
264
  val = 0;
130
1.74k
  while((ch = (unsigned char)*src++) != '\0') {
131
1.55k
    if(ISXDIGIT(ch)) {
132
1.01k
      val <<= 4;
133
1.01k
      val |= curlx_hexval(ch);
134
1.01k
      if(++saw_xdigit > 4)
135
6
        return 0;
136
1.00k
      continue;
137
1.01k
    }
138
541
    if(ch == ':') {
139
482
      curtok = src;
140
482
      if(!saw_xdigit) {
141
116
        if(colonp)
142
4
          return 0;
143
112
        colonp = tp;
144
112
        continue;
145
116
      }
146
366
      if(tp + INT16SZ > endp)
147
2
        return 0;
148
364
      *tp++ = (unsigned char)((val >> 8) & 0xff);
149
364
      *tp++ = (unsigned char)(val & 0xff);
150
364
      saw_xdigit = 0;
151
364
      val = 0;
152
364
      continue;
153
366
    }
154
59
    if(ch == '.' && ((tp + INADDRSZ) <= endp) &&
155
58
       inet_pton4(curtok, tp) > 0) {
156
3
      tp += INADDRSZ;
157
3
      saw_xdigit = 0;
158
3
      break;    /* '\0' was seen by inet_pton4(). */
159
3
    }
160
56
    return 0;
161
59
  }
162
196
  if(saw_xdigit) {
163
120
    if(tp + INT16SZ > endp)
164
1
      return 0;
165
119
    *tp++ = (unsigned char)((val >> 8) & 0xff);
166
119
    *tp++ = (unsigned char)(val & 0xff);
167
119
  }
168
195
  if(colonp) {
169
    /*
170
     * Since some memmove()'s erroneously fail to handle
171
     * overlapping regions, we do the shift by hand.
172
     */
173
107
    const ssize_t n = tp - colonp;
174
107
    ssize_t i;
175
176
107
    if(tp == endp)
177
1
      return 0;
178
516
    for(i = 1; i <= n; i++) {
179
410
      *(endp - i) = *(colonp + n - i);
180
410
      *(colonp + n - i) = 0;
181
410
    }
182
106
    tp = endp;
183
106
  }
184
194
  if(tp != endp)
185
82
    return 0;
186
112
  memcpy(dst, tmp, IN6ADDRSZ);
187
112
  return 1;
188
194
}
189
190
/*
191
 * Convert from presentation format (which usually means ASCII printable)
192
 * to network format (which is usually some kind of binary format).
193
 *
194
 * Return:
195
 *   1 if the address was valid for the specified address family
196
 *   0 if the address was not valid (`dst' is untouched in this case)
197
 *  -1 if some other error occurred (`dst' is untouched in this case, too)
198
 *
199
 * On Windows we store the error in the thread errno, not in the Winsock error
200
 * code. This is to avoid losing the actual last Winsock error. When this
201
 * function returns NULL, check errno not SOCKERRNO.
202
 *
203
 * author:
204
 *      Paul Vixie, 1996.
205
 */
206
int curlx_inet_pton(int af, const char *src, void *dst)
207
274
{
208
274
  switch(af) {
209
0
  case AF_INET:
210
0
    return inet_pton4(src, (unsigned char *)dst);
211
274
  case AF_INET6:
212
274
    return inet_pton6(src, (unsigned char *)dst);
213
0
  default:
214
0
    errno = SOCKEAFNOSUPPORT;
215
0
    return -1;
216
274
  }
217
  /* NOTREACHED */
218
274
}