Coverage Report

Created: 2026-09-14 07:12

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
3.66M
#define IN6ADDRSZ       16
36
2.09M
#define INADDRSZ         4
37
577k
#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
3.57M
{
64
3.57M
  int saw_digit, octets, ch;
65
3.57M
  unsigned char tmp[INADDRSZ], *tp;
66
67
3.57M
  saw_digit = 0;
68
3.57M
  octets = 0;
69
3.57M
  tp = tmp;
70
3.57M
  *tp = 0;
71
24.0M
  while((ch = (unsigned char)*src++) != '\0') {
72
22.0M
    if(ISDIGIT(ch)) {
73
14.5M
      unsigned int val = (*tp * 10) + (ch - '0');
74
75
14.5M
      if(saw_digit && *tp == 0)
76
30.8k
        return 0;
77
14.4M
      if(val > 255)
78
52.7k
        return 0;
79
14.4M
      *tp = (unsigned char)val;
80
14.4M
      if(!saw_digit) {
81
8.17M
        if(++octets > 4)
82
0
          return 0;
83
8.17M
        saw_digit = 1;
84
8.17M
      }
85
14.4M
    }
86
7.51M
    else if(ch == '.' && saw_digit) {
87
6.07M
      if(octets == 4)
88
17.8k
        return 0;
89
6.05M
      *++tp = 0;
90
6.05M
      saw_digit = 0;
91
6.05M
    }
92
1.43M
    else
93
1.43M
      return 0;
94
22.0M
  }
95
2.03M
  if(octets < 4)
96
90.6k
    return 0;
97
1.94M
  memcpy(dst, tmp, INADDRSZ);
98
1.94M
  return 1;
99
2.03M
}
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
1.70M
{
115
1.70M
  unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
116
1.70M
  const char *curtok;
117
1.70M
  int ch, saw_xdigit;
118
1.70M
  size_t val;
119
120
1.70M
  memset((tp = tmp), 0, IN6ADDRSZ);
121
1.70M
  endp = tp + IN6ADDRSZ;
122
1.70M
  colonp = NULL;
123
  /* Leading :: requires some special handling. */
124
1.70M
  if(*src == ':' && *++src != ':')
125
16.1k
    return 0;
126
1.69M
  curtok = src;
127
1.69M
  saw_xdigit = 0;
128
1.69M
  val = 0;
129
3.65M
  while((ch = (unsigned char)*src++) != '\0') {
130
3.24M
    if(ISXDIGIT(ch)) {
131
1.42M
      val <<= 4;
132
1.42M
      val |= curlx_hexval(ch);
133
1.42M
      if(++saw_xdigit > 4)
134
17.1k
        return 0;
135
1.40M
      continue;
136
1.42M
    }
137
1.82M
    if(ch == ':') {
138
566k
      curtok = src;
139
566k
      if(!saw_xdigit) {
140
255k
        if(colonp)
141
6.05k
          return 0;
142
249k
        colonp = tp;
143
249k
        continue;
144
255k
      }
145
311k
      if(tp + INT16SZ > endp)
146
1.12k
        return 0;
147
310k
      *tp++ = (unsigned char)((val >> 8) & 0xff);
148
310k
      *tp++ = (unsigned char)(val & 0xff);
149
310k
      saw_xdigit = 0;
150
310k
      val = 0;
151
310k
      continue;
152
311k
    }
153
1.25M
    if(ch == '.' && ((tp + INADDRSZ) <= endp) &&
154
139k
       inet_pton4(curtok, tp) > 0) {
155
11.2k
      tp += INADDRSZ;
156
11.2k
      saw_xdigit = 0;
157
11.2k
      break;    /* '\0' was seen by inet_pton4(). */
158
11.2k
    }
159
1.24M
    return 0;
160
1.25M
  }
161
423k
  if(saw_xdigit) {
162
266k
    if(tp + INT16SZ > endp)
163
1.22k
      return 0;
164
265k
    *tp++ = (unsigned char)((val >> 8) & 0xff);
165
265k
    *tp++ = (unsigned char)(val & 0xff);
166
265k
  }
167
422k
  if(colonp) {
168
    /*
169
     * Since some memmove()'s erroneously fail to handle
170
     * overlapping regions, we do the shift by hand.
171
     */
172
234k
    const ssize_t n = tp - colonp;
173
234k
    ssize_t i;
174
175
234k
    if(tp == endp)
176
864
      return 0;
177
672k
    for(i = 1; i <= n; i++) {
178
439k
      *(endp - i) = *(colonp + n - i);
179
439k
      *(colonp + n - i) = 0;
180
439k
    }
181
233k
    tp = endp;
182
233k
  }
183
421k
  if(tp != endp)
184
176k
    return 0;
185
245k
  memcpy(dst, tmp, IN6ADDRSZ);
186
245k
  return 1;
187
421k
}
188
189
/*
190
 * Convert from presentation format (which usually means ASCII printable)
191
 * to network format (which is usually some kind of binary format).
192
 *
193
 * Return:
194
 *   1 if the address was valid for the specified address family
195
 *   0 if the address was not valid (`dst' is untouched in this case)
196
 *  -1 if some other error occurred (`dst' is untouched in this case, too)
197
 *
198
 * author:
199
 *      Paul Vixie, 1996.
200
 */
201
int curlx_inet_pton(int af, const char *src, void *dst)
202
5.14M
{
203
5.14M
  switch(af) {
204
3.43M
  case AF_INET:
205
3.43M
    return inet_pton4(src, (unsigned char *)dst);
206
1.70M
  case AF_INET6:
207
1.70M
    return inet_pton6(src, (unsigned char *)dst);
208
0
  default:
209
0
    return -1;
210
5.14M
  }
211
  /* NOTREACHED */
212
5.14M
}