Coverage Report

Created: 2026-10-28 07:17

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
2.78M
#define IN6ADDRSZ       16
36
1.72M
#define INADDRSZ         4
37
477k
#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
2.75M
{
64
2.75M
  int saw_digit, octets, ch;
65
2.75M
  unsigned char tmp[INADDRSZ], *tp;
66
67
2.75M
  saw_digit = 0;
68
2.75M
  octets = 0;
69
2.75M
  tp = tmp;
70
2.75M
  *tp = 0;
71
19.5M
  while((ch = (unsigned char)*src++) != '\0') {
72
17.8M
    if(ISDIGIT(ch)) {
73
11.9M
      unsigned int val = (*tp * 10) + (ch - '0');
74
75
11.9M
      if(saw_digit && *tp == 0)
76
18.8k
        return 0;
77
11.9M
      if(val > 255)
78
35.5k
        return 0;
79
11.8M
      *tp = (unsigned char)val;
80
11.8M
      if(!saw_digit) {
81
6.70M
        if(++octets > 4)
82
0
          return 0;
83
6.70M
        saw_digit = 1;
84
6.70M
      }
85
11.8M
    }
86
5.93M
    else if(ch == '.' && saw_digit) {
87
4.97M
      if(octets == 4)
88
15.6k
        return 0;
89
4.95M
      *++tp = 0;
90
4.95M
      saw_digit = 0;
91
4.95M
    }
92
958k
    else
93
958k
      return 0;
94
17.8M
  }
95
1.72M
  if(octets < 4)
96
124k
    return 0;
97
1.60M
  memcpy(dst, tmp, INADDRSZ);
98
1.60M
  return 1;
99
1.72M
}
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.27M
{
115
1.27M
  unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
116
1.27M
  const char *curtok;
117
1.27M
  int ch, saw_xdigit;
118
1.27M
  size_t val;
119
120
1.27M
  memset((tp = tmp), 0, IN6ADDRSZ);
121
1.27M
  endp = tp + IN6ADDRSZ;
122
1.27M
  colonp = NULL;
123
  /* Leading :: requires some special handling. */
124
1.27M
  if(*src == ':' && *++src != ':')
125
20.4k
    return 0;
126
1.25M
  curtok = src;
127
1.25M
  saw_xdigit = 0;
128
1.25M
  val = 0;
129
2.87M
  while((ch = (unsigned char)*src++) != '\0') {
130
2.46M
    if(ISXDIGIT(ch)) {
131
1.13M
      val <<= 4;
132
1.13M
      val |= curlx_hexval(ch);
133
1.13M
      if(++saw_xdigit > 4)
134
19.9k
        return 0;
135
1.11M
      continue;
136
1.13M
    }
137
1.33M
    if(ch == ':') {
138
528k
      curtok = src;
139
528k
      if(!saw_xdigit) {
140
270k
        if(colonp)
141
8.05k
          return 0;
142
262k
        colonp = tp;
143
262k
        continue;
144
270k
      }
145
258k
      if(!*src)
146
5.64k
        return 0;
147
252k
      if(tp + INT16SZ > endp)
148
2.26k
        return 0;
149
250k
      *tp++ = (unsigned char)((val >> 8) & 0xff);
150
250k
      *tp++ = (unsigned char)(val & 0xff);
151
250k
      saw_xdigit = 0;
152
250k
      val = 0;
153
250k
      continue;
154
252k
    }
155
804k
    if(ch == '.' && ((tp + INADDRSZ) <= endp) &&
156
107k
       inet_pton4(curtok, tp) > 0) {
157
16.0k
      tp += INADDRSZ;
158
16.0k
      saw_xdigit = 0;
159
16.0k
      break;    /* '\0' was seen by inet_pton4(). */
160
16.0k
    }
161
788k
    return 0;
162
804k
  }
163
429k
  if(saw_xdigit) {
164
224k
    if(tp + INT16SZ > endp)
165
2.01k
      return 0;
166
222k
    *tp++ = (unsigned char)((val >> 8) & 0xff);
167
222k
    *tp++ = (unsigned char)(val & 0xff);
168
222k
  }
169
427k
  if(colonp) {
170
    /*
171
     * Since some memmove()'s erroneously fail to handle
172
     * overlapping regions, we do the shift by hand.
173
     */
174
240k
    const ssize_t n = tp - colonp;
175
240k
    ssize_t i;
176
177
240k
    if(tp == endp)
178
2.48k
      return 0;
179
632k
    for(i = 1; i <= n; i++) {
180
394k
      *(endp - i) = *(colonp + n - i);
181
394k
      *(colonp + n - i) = 0;
182
394k
    }
183
237k
    tp = endp;
184
237k
  }
185
425k
  if(tp != endp)
186
185k
    return 0;
187
240k
  memcpy(dst, tmp, IN6ADDRSZ);
188
240k
  return 1;
189
425k
}
190
191
/*
192
 * Convert from presentation format (which usually means ASCII printable)
193
 * to network format (which is usually some kind of binary format).
194
 *
195
 * Return:
196
 *   1 if the address was valid for the specified address family
197
 *   0 if the address was not valid (`dst' is untouched in this case)
198
 *  -1 if some other error occurred (`dst' is untouched in this case, too)
199
 *
200
 * author:
201
 *      Paul Vixie, 1996.
202
 */
203
int curlx_inet_pton(int af, const char *src, void *dst)
204
3.92M
{
205
3.92M
  switch(af) {
206
2.64M
  case AF_INET:
207
2.64M
    return inet_pton4(src, (unsigned char *)dst);
208
1.27M
  case AF_INET6:
209
1.27M
    return inet_pton6(src, (unsigned char *)dst);
210
0
  default:
211
0
    return -1;
212
3.92M
  }
213
  /* NOTREACHED */
214
3.92M
}