• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1From f22cc01039b6473b736d3bf438f56a2654cdf2b2 Mon Sep 17 00:00:00 2001
2From: Brad House <brad@brad-house.com>
3Date: Mon, 22 May 2023 06:51:34 -0400
4Subject: [PATCH] Merge pull request from GHSA-x6mf-cxr9-8q6v
5
6* Merged latest OpenBSD changes for inet_net_pton_ipv6() into c-ares.
7* Always use our own IP conversion functions now, do not delegate to OS
8  so we can have consistency in testing and fuzzing.
9* Removed bogus test cases that never should have passed.
10* Add new test case for crash bug found.
11
12Fix By: Brad House (@bradh352)
13---
14 src/lib/inet_net_pton.c    | 155 ++++++++++++++++++++-----------------
15 test/ares-test-internal.cc |   7 +-
16 2 files changed, 86 insertions(+), 76 deletions(-)
17
18diff --git a/src/lib/inet_net_pton.c b/src/lib/inet_net_pton.c
19index 840de50..fc50425 100644
20--- a/src/lib/inet_net_pton.c
21+++ b/src/lib/inet_net_pton.c
22@@ -1,19 +1,20 @@
23
24 /*
25- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
26+ * Copyright (c) 2012 by Gilles Chehade <gilles@openbsd.org>
27  * Copyright (c) 1996,1999 by Internet Software Consortium.
28  *
29  * Permission to use, copy, modify, and distribute this software for any
30  * purpose with or without fee is hereby granted, provided that the above
31  * copyright notice and this permission notice appear in all copies.
32  *
33- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
34- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
35- * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
36- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
37- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
38- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
39- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
40+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
41+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
42+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
43+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
44+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
45+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
46+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47+ * SOFTWARE.
48  */
49
50 #include "ares_setup.h"
51@@ -35,9 +36,6 @@
52
53 const struct ares_in6_addr ares_in6addr_any = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
54
55-
56-#ifndef HAVE_INET_NET_PTON
57-
58 /*
59  * static int
60  * inet_net_pton_ipv4(src, dst, size)
61@@ -60,7 +58,7 @@ const struct ares_in6_addr ares_in6addr_any = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62  *      Paul Vixie (ISC), June 1996
63  */
64 static int
65-inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
66+ares_inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size)
67 {
68   static const char xdigits[] = "0123456789abcdef";
69   static const char digits[] = "0123456789";
70@@ -261,19 +259,14 @@ getv4(const char *src, unsigned char *dst, int *bitsp)
71 }
72
73 static int
74-inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
75+ares_inet_pton6(const char *src, unsigned char *dst)
76 {
77   static const char xdigits_l[] = "0123456789abcdef",
78-    xdigits_u[] = "0123456789ABCDEF";
79+        xdigits_u[] = "0123456789ABCDEF";
80   unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
81   const char *xdigits, *curtok;
82-  int ch, saw_xdigit;
83+  int ch, saw_xdigit, count_xdigit;
84   unsigned int val;
85-  int digits;
86-  int bits;
87-  size_t bytes;
88-  int words;
89-  int ipv4;
90
91   memset((tp = tmp), '\0', NS_IN6ADDRSZ);
92   endp = tp + NS_IN6ADDRSZ;
93@@ -283,22 +276,22 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
94     if (*++src != ':')
95       goto enoent;
96   curtok = src;
97-  saw_xdigit = 0;
98+  saw_xdigit = count_xdigit = 0;
99   val = 0;
100-  digits = 0;
101-  bits = -1;
102-  ipv4 = 0;
103   while ((ch = *src++) != '\0') {
104     const char *pch;
105
106     if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
107       pch = strchr((xdigits = xdigits_u), ch);
108     if (pch != NULL) {
109+      if (count_xdigit >= 4)
110+        goto enoent;
111       val <<= 4;
112-      val |= aresx_sztoui(pch - xdigits);
113-      if (++digits > 4)
114+      val |= (pch - xdigits);
115+      if (val > 0xffff)
116         goto enoent;
117       saw_xdigit = 1;
118+      count_xdigit++;
119       continue;
120     }
121     if (ch == ':') {
122@@ -308,78 +301,107 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
123           goto enoent;
124         colonp = tp;
125         continue;
126-      } else if (*src == '\0')
127+      } else if (*src == '\0') {
128         goto enoent;
129+      }
130       if (tp + NS_INT16SZ > endp)
131-        return (0);
132-      *tp++ = (unsigned char)((val >> 8) & 0xff);
133-      *tp++ = (unsigned char)(val & 0xff);
134+        goto enoent;
135+      *tp++ = (unsigned char) (val >> 8) & 0xff;
136+      *tp++ = (unsigned char) val & 0xff;
137       saw_xdigit = 0;
138-      digits = 0;
139+      count_xdigit = 0;
140       val = 0;
141       continue;
142     }
143     if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
144-        getv4(curtok, tp, &bits) > 0) {
145-      tp += NS_INADDRSZ;
146+        ares_inet_net_pton_ipv4(curtok, tp, INADDRSZ) > 0) {
147+      tp += INADDRSZ;
148       saw_xdigit = 0;
149-      ipv4 = 1;
150+      count_xdigit = 0;
151       break;  /* '\0' was seen by inet_pton4(). */
152     }
153-    if (ch == '/' && getbits(src, &bits) > 0)
154-      break;
155     goto enoent;
156   }
157   if (saw_xdigit) {
158     if (tp + NS_INT16SZ > endp)
159       goto enoent;
160-    *tp++ = (unsigned char)((val >> 8) & 0xff);
161-    *tp++ = (unsigned char)(val & 0xff);
162+    *tp++ = (unsigned char) (val >> 8) & 0xff;
163+    *tp++ = (unsigned char) val & 0xff;
164   }
165-  if (bits == -1)
166-    bits = 128;
167-
168-  words = (bits + 15) / 16;
169-  if (words < 2)
170-    words = 2;
171-  if (ipv4)
172-    words = 8;
173-  endp =  tmp + 2 * words;
174-
175   if (colonp != NULL) {
176     /*
177      * Since some memmove()'s erroneously fail to handle
178      * overlapping regions, we'll do the shift by hand.
179      */
180-    const ares_ssize_t n = tp - colonp;
181-    ares_ssize_t i;
182+    const int n = tp - colonp;
183+    int i;
184
185     if (tp == endp)
186       goto enoent;
187     for (i = 1; i <= n; i++) {
188-      *(endp - i) = *(colonp + n - i);
189-      *(colonp + n - i) = 0;
190+      endp[- i] = colonp[n - i];
191+      colonp[n - i] = 0;
192     }
193     tp = endp;
194   }
195   if (tp != endp)
196     goto enoent;
197
198-  bytes = (bits + 7) / 8;
199-  if (bytes > size)
200-    goto emsgsize;
201-  memcpy(dst, tmp, bytes);
202-  return (bits);
203+  memcpy(dst, tmp, NS_IN6ADDRSZ);
204+  return (1);
205
206-  enoent:
207+enoent:
208   SET_ERRNO(ENOENT);
209   return (-1);
210
211-  emsgsize:
212+emsgsize:
213   SET_ERRNO(EMSGSIZE);
214   return (-1);
215 }
216
217+static int
218+ares_inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size)
219+{
220+  struct ares_in6_addr in6;
221+  int                  ret;
222+  int                  bits;
223+  size_t               bytes;
224+  char                 buf[INET6_ADDRSTRLEN + sizeof("/128")];
225+  char                *sep;
226+  const char          *errstr;
227+
228+  if (strlen(src) >= sizeof buf) {
229+    SET_ERRNO(EMSGSIZE);
230+    return (-1);
231+  }
232+  strncpy(buf, src, sizeof buf);
233+
234+  sep = strchr(buf, '/');
235+  if (sep != NULL)
236+    *sep++ = '\0';
237+
238+  ret = ares_inet_pton6(buf, (unsigned char *)&in6);
239+  if (ret != 1)
240+    return (-1);
241+
242+  if (sep == NULL)
243+    bits = 128;
244+  else {
245+    if (!getbits(sep, &bits)) {
246+      SET_ERRNO(ENOENT);
247+      return (-1);
248+    }
249+  }
250+
251+  bytes = (bits + 7) / 8;
252+  if (bytes > size) {
253+    SET_ERRNO(EMSGSIZE);
254+    return (-1);
255+  }
256+  memcpy(dst, &in6, bytes);
257+  return (bits);
258+}
259+
260 /*
261  * int
262  * inet_net_pton(af, src, dst, size)
263@@ -403,18 +425,15 @@ ares_inet_net_pton(int af, const char *src, void *dst, size_t size)
264 {
265   switch (af) {
266   case AF_INET:
267-    return (inet_net_pton_ipv4(src, dst, size));
268+    return (ares_inet_net_pton_ipv4(src, dst, size));
269   case AF_INET6:
270-    return (inet_net_pton_ipv6(src, dst, size));
271+    return (ares_inet_net_pton_ipv6(src, dst, size));
272   default:
273     SET_ERRNO(EAFNOSUPPORT);
274     return (-1);
275   }
276 }
277
278-#endif /* HAVE_INET_NET_PTON */
279-
280-#ifndef HAVE_INET_PTON
281 int ares_inet_pton(int af, const char *src, void *dst)
282 {
283   int result;
284@@ -434,11 +453,3 @@ int ares_inet_pton(int af, const char *src, void *dst)
285     return 0;
286   return (result > -1 ? 1 : -1);
287 }
288-#else /* HAVE_INET_PTON */
289-int ares_inet_pton(int af, const char *src, void *dst)
290-{
291-  /* just relay this to the underlying function */
292-  return inet_pton(af, src, dst);
293-}
294-
295-#endif
296diff --git a/test/ares-test-internal.cc b/test/ares-test-internal.cc
297index 1cb7e42..40cc82b 100644
298--- a/test/ares-test-internal.cc
299+++ b/test/ares-test-internal.cc
300@@ -123,6 +123,7 @@ TEST_F(LibraryTest, InetPtoN) {
301   EXPECT_EQ(0, ares_inet_net_pton(AF_INET6, "12:34::ff/0", &a6, sizeof(a6)));
302   EXPECT_EQ(16 * 8, ares_inet_net_pton(AF_INET6, "12:34::ffff:0.2", &a6, sizeof(a6)));
303   EXPECT_EQ(16 * 8, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234", &a6, sizeof(a6)));
304+  EXPECT_EQ(2, ares_inet_net_pton(AF_INET6, "0::00:00:00/2", &a6, sizeof(a6)));
305
306   // Various malformed versions
307   EXPECT_EQ(-1, ares_inet_net_pton(AF_INET, "", &a4, sizeof(a4)));
308@@ -160,11 +161,9 @@ TEST_F(LibraryTest, InetPtoN) {
309   EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, ":1234:1234:1234:1234:1234:1234:1234:1234", &a6, sizeof(a6)));
310   EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, ":1234:1234:1234:1234:1234:1234:1234:1234:", &a6, sizeof(a6)));
311   EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234:5678", &a6, sizeof(a6)));
312-  // TODO(drysdale): check whether the next two tests should give -1.
313-  EXPECT_EQ(0, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234:5678:5678", &a6, sizeof(a6)));
314-  EXPECT_EQ(0, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234:5678:5678:5678", &a6, sizeof(a6)));
315+  EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234:5678:5678", &a6, sizeof(a6)));
316+  EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234:5678:5678:5678", &a6, sizeof(a6)));
317   EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "12:34::ffff:257.2.3.4", &a6, sizeof(a6)));
318-  EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "12:34::ffff:002.2.3.4", &a6, sizeof(a6)));
319   EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "12:34::ffff:1.2.3.4.5.6", &a6, sizeof(a6)));
320   EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "12:34::ffff:1.2.3.4.5", &a6, sizeof(a6)));
321   EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "12:34::ffff:1.2.3.z", &a6, sizeof(a6)));
322--
3232.27.0
324
325