Skip to content

Commit a71db81

Browse files
aaronmereyfberat
andcommitted
Prepare inet_pton to be fortified
Split inet_pton internals such as __inet_pton_length from the inet_pton entry point. This allows the internals to be built with fortification while leaving the inet_pton entry point unchanged. Co-authored-by: Frédéric Bérat <[email protected]> Reviewed-by: Florian Weimer <[email protected]>
1 parent 2fb0009 commit a71db81

File tree

3 files changed

+229
-187
lines changed

3 files changed

+229
-187
lines changed

resolv/Makefile

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ routines := \
3838
inet_addr \
3939
inet_ntop \
4040
inet_pton \
41+
inet_pton_length \
4142
ns_makecanon \
4243
ns_name_compress \
4344
ns_name_length_uncompressed \
@@ -73,6 +74,11 @@ routines := \
7374
resolv_context \
7475
# routines
7576

77+
# Exclude fortified routines from being built with _FORTIFY_SOURCE
78+
routines_no_fortify += \
79+
inet_pton \
80+
# routines_no_fortify
81+
7682
tests = tst-aton tst-leaks tst-inet_ntop
7783
tests-container = tst-leaks2
7884

resolv/inet_pton.c

-187
Original file line numberDiff line numberDiff line change
@@ -33,33 +33,7 @@
3333
*/
3434

3535
#include <arpa/inet.h>
36-
#include <arpa/nameser.h>
37-
#include <ctype.h>
38-
#include <errno.h>
39-
#include <netinet/in.h>
4036
#include <resolv/resolv-internal.h>
41-
#include <string.h>
42-
#include <sys/socket.h>
43-
#include <sys/types.h>
44-
45-
static int inet_pton4 (const char *src, const char *src_end, u_char *dst);
46-
static int inet_pton6 (const char *src, const char *src_end, u_char *dst);
47-
48-
int
49-
__inet_pton_length (int af, const char *src, size_t srclen, void *dst)
50-
{
51-
switch (af)
52-
{
53-
case AF_INET:
54-
return inet_pton4 (src, src + srclen, dst);
55-
case AF_INET6:
56-
return inet_pton6 (src, src + srclen, dst);
57-
default:
58-
__set_errno (EAFNOSUPPORT);
59-
return -1;
60-
}
61-
}
62-
libc_hidden_def (__inet_pton_length)
6337

6438
/* Like __inet_pton_length, but use strlen (SRC) as the length of
6539
SRC. */
@@ -71,164 +45,3 @@ __inet_pton (int af, const char *src, void *dst)
7145
libc_hidden_def (__inet_pton)
7246
weak_alias (__inet_pton, inet_pton)
7347
libc_hidden_weak (inet_pton)
74-
75-
/* Like inet_aton but without all the hexadecimal, octal and shorthand
76-
(and trailing garbage is not ignored). Return 1 if SRC is a valid
77-
dotted quad, else 0. This function does not touch DST unless it's
78-
returning 1.
79-
Author: Paul Vixie, 1996. */
80-
static int
81-
inet_pton4 (const char *src, const char *end, unsigned char *dst)
82-
{
83-
int saw_digit, octets, ch;
84-
unsigned char tmp[NS_INADDRSZ], *tp;
85-
86-
saw_digit = 0;
87-
octets = 0;
88-
*(tp = tmp) = 0;
89-
while (src < end)
90-
{
91-
ch = *src++;
92-
if (ch >= '0' && ch <= '9')
93-
{
94-
unsigned int new = *tp * 10 + (ch - '0');
95-
96-
if (saw_digit && *tp == 0)
97-
return 0;
98-
if (new > 255)
99-
return 0;
100-
*tp = new;
101-
if (! saw_digit)
102-
{
103-
if (++octets > 4)
104-
return 0;
105-
saw_digit = 1;
106-
}
107-
}
108-
else if (ch == '.' && saw_digit)
109-
{
110-
if (octets == 4)
111-
return 0;
112-
*++tp = 0;
113-
saw_digit = 0;
114-
}
115-
else
116-
return 0;
117-
}
118-
if (octets < 4)
119-
return 0;
120-
memcpy (dst, tmp, NS_INADDRSZ);
121-
return 1;
122-
}
123-
124-
/* Return the value of CH as a hexadecimal digit, or -1 if it is a
125-
different type of character. */
126-
static int
127-
hex_digit_value (char ch)
128-
{
129-
if ('0' <= ch && ch <= '9')
130-
return ch - '0';
131-
if ('a' <= ch && ch <= 'f')
132-
return ch - 'a' + 10;
133-
if ('A' <= ch && ch <= 'F')
134-
return ch - 'A' + 10;
135-
return -1;
136-
}
137-
138-
/* Convert presentation-level IPv6 address to network order binary
139-
form. Return 1 if SRC is a valid [RFC1884 2.2] address, else 0.
140-
This function does not touch DST unless it's returning 1.
141-
Author: Paul Vixie, 1996. Inspired by Mark Andrews. */
142-
static int
143-
inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
144-
{
145-
unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
146-
const char *curtok;
147-
int ch;
148-
size_t xdigits_seen; /* Number of hex digits since colon. */
149-
unsigned int val;
150-
151-
tp = memset (tmp, '\0', NS_IN6ADDRSZ);
152-
endp = tp + NS_IN6ADDRSZ;
153-
colonp = NULL;
154-
155-
/* Leading :: requires some special handling. */
156-
if (src == src_endp)
157-
return 0;
158-
if (*src == ':')
159-
{
160-
++src;
161-
if (src == src_endp || *src != ':')
162-
return 0;
163-
}
164-
165-
curtok = src;
166-
xdigits_seen = 0;
167-
val = 0;
168-
while (src < src_endp)
169-
{
170-
ch = *src++;
171-
int digit = hex_digit_value (ch);
172-
if (digit >= 0)
173-
{
174-
if (xdigits_seen == 4)
175-
return 0;
176-
val <<= 4;
177-
val |= digit;
178-
if (val > 0xffff)
179-
return 0;
180-
++xdigits_seen;
181-
continue;
182-
}
183-
if (ch == ':')
184-
{
185-
curtok = src;
186-
if (xdigits_seen == 0)
187-
{
188-
if (colonp)
189-
return 0;
190-
colonp = tp;
191-
continue;
192-
}
193-
else if (src == src_endp)
194-
return 0;
195-
if (tp + NS_INT16SZ > endp)
196-
return 0;
197-
*tp++ = (unsigned char) (val >> 8) & 0xff;
198-
*tp++ = (unsigned char) val & 0xff;
199-
xdigits_seen = 0;
200-
val = 0;
201-
continue;
202-
}
203-
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp)
204-
&& inet_pton4 (curtok, src_endp, tp) > 0)
205-
{
206-
tp += NS_INADDRSZ;
207-
xdigits_seen = 0;
208-
break; /* '\0' was seen by inet_pton4. */
209-
}
210-
return 0;
211-
}
212-
if (xdigits_seen > 0)
213-
{
214-
if (tp + NS_INT16SZ > endp)
215-
return 0;
216-
*tp++ = (unsigned char) (val >> 8) & 0xff;
217-
*tp++ = (unsigned char) val & 0xff;
218-
}
219-
if (colonp != NULL)
220-
{
221-
/* Replace :: with zeros. */
222-
if (tp == endp)
223-
/* :: would expand to a zero-width field. */
224-
return 0;
225-
size_t n = tp - colonp;
226-
memmove (endp - n, colonp, n);
227-
memset (colonp, 0, endp - n - colonp);
228-
tp = endp;
229-
}
230-
if (tp != endp)
231-
return 0;
232-
memcpy (dst, tmp, NS_IN6ADDRSZ);
233-
return 1;
234-
}

0 commit comments

Comments
 (0)