Coverage Report

Created: 2026-09-14 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmcurl/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
0
#define IN6ADDRSZ       16
36
0
#define INADDRSZ         4
37
0
#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
0
{
64
0
  int saw_digit, octets, ch;
65
0
  unsigned char tmp[INADDRSZ], *tp;
66
67
0
  saw_digit = 0;
68
0
  octets = 0;
69
0
  tp = tmp;
70
0
  *tp = 0;
71
0
  while((ch = (unsigned char)*src++) != '\0') {
72
0
    if(ISDIGIT(ch)) {
73
0
      unsigned int val = (*tp * 10) + (ch - '0');
74
75
0
      if(saw_digit && *tp == 0)
76
0
        return 0;
77
0
      if(val > 255)
78
0
        return 0;
79
0
      *tp = (unsigned char)val;
80
0
      if(!saw_digit) {
81
0
        if(++octets > 4)
82
0
          return 0;
83
0
        saw_digit = 1;
84
0
      }
85
0
    }
86
0
    else if(ch == '.' && saw_digit) {
87
0
      if(octets == 4)
88
0
        return 0;
89
0
      *++tp = 0;
90
0
      saw_digit = 0;
91
0
    }
92
0
    else
93
0
      return 0;
94
0
  }
95
0
  if(octets < 4)
96
0
    return 0;
97
0
  memcpy(dst, tmp, INADDRSZ);
98
0
  return 1;
99
0
}
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
0
{
115
0
  unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
116
0
  const char *curtok;
117
0
  int ch, saw_xdigit;
118
0
  size_t val;
119
120
0
  memset((tp = tmp), 0, IN6ADDRSZ);
121
0
  endp = tp + IN6ADDRSZ;
122
0
  colonp = NULL;
123
  /* Leading :: requires some special handling. */
124
0
  if(*src == ':')
125
0
    if(*++src != ':')
126
0
      return 0;
127
0
  curtok = src;
128
0
  saw_xdigit = 0;
129
0
  val = 0;
130
0
  while((ch = (unsigned char)*src++) != '\0') {
131
0
    if(ISXDIGIT(ch)) {
132
0
      val <<= 4;
133
0
      val |= curlx_hexval(ch);
134
0
      if(++saw_xdigit > 4)
135
0
        return 0;
136
0
      continue;
137
0
    }
138
0
    if(ch == ':') {
139
0
      curtok = src;
140
0
      if(!saw_xdigit) {
141
0
        if(colonp)
142
0
          return 0;
143
0
        colonp = tp;
144
0
        continue;
145
0
      }
146
0
      if(tp + INT16SZ > endp)
147
0
        return 0;
148
0
      *tp++ = (unsigned char)((val >> 8) & 0xff);
149
0
      *tp++ = (unsigned char)(val & 0xff);
150
0
      saw_xdigit = 0;
151
0
      val = 0;
152
0
      continue;
153
0
    }
154
0
    if(ch == '.' && ((tp + INADDRSZ) <= endp) &&
155
0
       inet_pton4(curtok, tp) > 0) {
156
0
      tp += INADDRSZ;
157
0
      saw_xdigit = 0;
158
0
      break;    /* '\0' was seen by inet_pton4(). */
159
0
    }
160
0
    return 0;
161
0
  }
162
0
  if(saw_xdigit) {
163
0
    if(tp + INT16SZ > endp)
164
0
      return 0;
165
0
    *tp++ = (unsigned char)((val >> 8) & 0xff);
166
0
    *tp++ = (unsigned char)(val & 0xff);
167
0
  }
168
0
  if(colonp) {
169
    /*
170
     * Since some memmove()'s erroneously fail to handle
171
     * overlapping regions, we do the shift by hand.
172
     */
173
0
    const ssize_t n = tp - colonp;
174
0
    ssize_t i;
175
176
0
    if(tp == endp)
177
0
      return 0;
178
0
    for(i = 1; i <= n; i++) {
179
0
      *(endp - i) = *(colonp + n - i);
180
0
      *(colonp + n - i) = 0;
181
0
    }
182
0
    tp = endp;
183
0
  }
184
0
  if(tp != endp)
185
0
    return 0;
186
0
  memcpy(dst, tmp, IN6ADDRSZ);
187
0
  return 1;
188
0
}
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
 * author:
200
 *      Paul Vixie, 1996.
201
 */
202
int curlx_inet_pton(int af, const char *src, void *dst)
203
0
{
204
0
  switch(af) {
205
0
  case AF_INET:
206
0
    return inet_pton4(src, (unsigned char *)dst);
207
0
  case AF_INET6:
208
0
    return inet_pton6(src, (unsigned char *)dst);
209
0
  default:
210
0
    return -1;
211
0
  }
212
  /* NOTREACHED */
213
0
}