1 | //! A private parser implementation of IPv4, IPv6, and socket addresses. |
2 | //! |
3 | //! This module is "publicly exported" through the `FromStr` implementations |
4 | //! below. |
5 | |
6 | use crate::error::Error; |
7 | use crate::fmt; |
8 | use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; |
9 | use crate::str::FromStr; |
10 | |
11 | trait ReadNumberHelper: Sized { |
12 | const ZERO: Self; |
13 | fn checked_mul(&self, other: u32) -> Option<Self>; |
14 | fn checked_add(&self, other: u32) -> Option<Self>; |
15 | } |
16 | |
17 | macro_rules! impl_helper { |
18 | ($($t:ty)*) => ($(impl ReadNumberHelper for $t { |
19 | const ZERO: Self = 0; |
20 | #[inline] |
21 | fn checked_mul(&self, other: u32) -> Option<Self> { |
22 | Self::checked_mul(*self, other.try_into().ok()?) |
23 | } |
24 | #[inline] |
25 | fn checked_add(&self, other: u32) -> Option<Self> { |
26 | Self::checked_add(*self, other.try_into().ok()?) |
27 | } |
28 | })*) |
29 | } |
30 | |
31 | impl_helper! { u8 u16 u32 } |
32 | |
33 | struct Parser<'a> { |
34 | // Parsing as ASCII, so can use byte array. |
35 | state: &'a [u8], |
36 | } |
37 | |
38 | impl<'a> Parser<'a> { |
39 | fn new(input: &'a [u8]) -> Parser<'a> { |
40 | Parser { state: input } |
41 | } |
42 | |
43 | /// Run a parser, and restore the pre-parse state if it fails. |
44 | fn read_atomically<T, F>(&mut self, inner: F) -> Option<T> |
45 | where |
46 | F: FnOnce(&mut Parser<'_>) -> Option<T>, |
47 | { |
48 | let state = self.state; |
49 | let result = inner(self); |
50 | if result.is_none() { |
51 | self.state = state; |
52 | } |
53 | result |
54 | } |
55 | |
56 | /// Run a parser, but fail if the entire input wasn't consumed. |
57 | /// Doesn't run atomically. |
58 | fn parse_with<T, F>(&mut self, inner: F, kind: AddrKind) -> Result<T, AddrParseError> |
59 | where |
60 | F: FnOnce(&mut Parser<'_>) -> Option<T>, |
61 | { |
62 | let result = inner(self); |
63 | if self.state.is_empty() { result } else { None }.ok_or(AddrParseError(kind)) |
64 | } |
65 | |
66 | /// Peek the next character from the input |
67 | fn peek_char(&self) -> Option<char> { |
68 | self.state.first().map(|&b| char::from(b)) |
69 | } |
70 | |
71 | /// Read the next character from the input |
72 | fn read_char(&mut self) -> Option<char> { |
73 | self.state.split_first().map(|(&b, tail)| { |
74 | self.state = tail; |
75 | char::from(b) |
76 | }) |
77 | } |
78 | |
79 | #[must_use ] |
80 | /// Read the next character from the input if it matches the target. |
81 | fn read_given_char(&mut self, target: char) -> Option<()> { |
82 | self.read_atomically(|p| { |
83 | p.read_char().and_then(|c| if c == target { Some(()) } else { None }) |
84 | }) |
85 | } |
86 | |
87 | /// Helper for reading separators in an indexed loop. Reads the separator |
88 | /// character iff index > 0, then runs the parser. When used in a loop, |
89 | /// the separator character will only be read on index > 0 (see |
90 | /// read_ipv4_addr for an example) |
91 | fn read_separator<T, F>(&mut self, sep: char, index: usize, inner: F) -> Option<T> |
92 | where |
93 | F: FnOnce(&mut Parser<'_>) -> Option<T>, |
94 | { |
95 | self.read_atomically(move |p| { |
96 | if index > 0 { |
97 | p.read_given_char(sep)?; |
98 | } |
99 | inner(p) |
100 | }) |
101 | } |
102 | |
103 | // Read a number off the front of the input in the given radix, stopping |
104 | // at the first non-digit character or eof. Fails if the number has more |
105 | // digits than max_digits or if there is no number. |
106 | // |
107 | // INVARIANT: `max_digits` must be less than the number of digits that `u32` |
108 | // can represent. |
109 | fn read_number<T: ReadNumberHelper + TryFrom<u32>>( |
110 | &mut self, |
111 | radix: u32, |
112 | max_digits: Option<usize>, |
113 | allow_zero_prefix: bool, |
114 | ) -> Option<T> { |
115 | // If max_digits.is_some(), then we are parsing a `u8` or `u16` and |
116 | // don't need to use checked arithmetic since it fits within a `u32`. |
117 | if let Some(max_digits) = max_digits { |
118 | // u32::MAX = 4_294_967_295u32, which is 10 digits long. |
119 | // `max_digits` must be less than 10 to not overflow a `u32`. |
120 | debug_assert!(max_digits < 10); |
121 | |
122 | self.read_atomically(move |p| { |
123 | let mut result = 0_u32; |
124 | let mut digit_count = 0; |
125 | let has_leading_zero = p.peek_char() == Some('0' ); |
126 | |
127 | while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { |
128 | result *= radix; |
129 | result += digit; |
130 | digit_count += 1; |
131 | |
132 | if digit_count > max_digits { |
133 | return None; |
134 | } |
135 | } |
136 | |
137 | if digit_count == 0 { |
138 | None |
139 | } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 { |
140 | None |
141 | } else { |
142 | result.try_into().ok() |
143 | } |
144 | }) |
145 | } else { |
146 | self.read_atomically(move |p| { |
147 | let mut result = T::ZERO; |
148 | let mut digit_count = 0; |
149 | let has_leading_zero = p.peek_char() == Some('0' ); |
150 | |
151 | while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) { |
152 | result = result.checked_mul(radix)?; |
153 | result = result.checked_add(digit)?; |
154 | digit_count += 1; |
155 | } |
156 | |
157 | if digit_count == 0 { |
158 | None |
159 | } else if !allow_zero_prefix && has_leading_zero && digit_count > 1 { |
160 | None |
161 | } else { |
162 | Some(result) |
163 | } |
164 | }) |
165 | } |
166 | } |
167 | |
168 | /// Read an IPv4 address. |
169 | fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> { |
170 | self.read_atomically(|p| { |
171 | let mut groups = [0; 4]; |
172 | |
173 | for (i, slot) in groups.iter_mut().enumerate() { |
174 | *slot = p.read_separator('.' , i, |p| { |
175 | // Disallow octal number in IP string. |
176 | // https://tools.ietf.org/html/rfc6943#section-3.1.1 |
177 | p.read_number(10, Some(3), false) |
178 | })?; |
179 | } |
180 | |
181 | Some(groups.into()) |
182 | }) |
183 | } |
184 | |
185 | /// Read an IPv6 Address. |
186 | fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> { |
187 | /// Read a chunk of an IPv6 address into `groups`. Returns the number |
188 | /// of groups read, along with a bool indicating if an embedded |
189 | /// trailing IPv4 address was read. Specifically, read a series of |
190 | /// colon-separated IPv6 groups (0x0000 - 0xFFFF), with an optional |
191 | /// trailing embedded IPv4 address. |
192 | fn read_groups(p: &mut Parser<'_>, groups: &mut [u16]) -> (usize, bool) { |
193 | let limit = groups.len(); |
194 | |
195 | for (i, slot) in groups.iter_mut().enumerate() { |
196 | // Try to read a trailing embedded IPv4 address. There must be |
197 | // at least two groups left. |
198 | if i < limit - 1 { |
199 | let ipv4 = p.read_separator(':' , i, |p| p.read_ipv4_addr()); |
200 | |
201 | if let Some(v4_addr) = ipv4 { |
202 | let [one, two, three, four] = v4_addr.octets(); |
203 | groups[i + 0] = u16::from_be_bytes([one, two]); |
204 | groups[i + 1] = u16::from_be_bytes([three, four]); |
205 | return (i + 2, true); |
206 | } |
207 | } |
208 | |
209 | let group = p.read_separator(':' , i, |p| p.read_number(16, Some(4), true)); |
210 | |
211 | match group { |
212 | Some(g) => *slot = g, |
213 | None => return (i, false), |
214 | } |
215 | } |
216 | (groups.len(), false) |
217 | } |
218 | |
219 | self.read_atomically(|p| { |
220 | // Read the front part of the address; either the whole thing, or up |
221 | // to the first :: |
222 | let mut head = [0; 8]; |
223 | let (head_size, head_ipv4) = read_groups(p, &mut head); |
224 | |
225 | if head_size == 8 { |
226 | return Some(head.into()); |
227 | } |
228 | |
229 | // IPv4 part is not allowed before `::` |
230 | if head_ipv4 { |
231 | return None; |
232 | } |
233 | |
234 | // Read `::` if previous code parsed less than 8 groups. |
235 | // `::` indicates one or more groups of 16 bits of zeros. |
236 | p.read_given_char(':' )?; |
237 | p.read_given_char(':' )?; |
238 | |
239 | // Read the back part of the address. The :: must contain at least one |
240 | // set of zeroes, so our max length is 7. |
241 | let mut tail = [0; 7]; |
242 | let limit = 8 - (head_size + 1); |
243 | let (tail_size, _) = read_groups(p, &mut tail[..limit]); |
244 | |
245 | // Concat the head and tail of the IP address |
246 | head[(8 - tail_size)..8].copy_from_slice(&tail[..tail_size]); |
247 | |
248 | Some(head.into()) |
249 | }) |
250 | } |
251 | |
252 | /// Read an IP Address, either IPv4 or IPv6. |
253 | fn read_ip_addr(&mut self) -> Option<IpAddr> { |
254 | self.read_ipv4_addr().map(IpAddr::V4).or_else(move || self.read_ipv6_addr().map(IpAddr::V6)) |
255 | } |
256 | |
257 | /// Read a `:` followed by a port in base 10. |
258 | fn read_port(&mut self) -> Option<u16> { |
259 | self.read_atomically(|p| { |
260 | p.read_given_char(':' )?; |
261 | p.read_number(10, None, true) |
262 | }) |
263 | } |
264 | |
265 | /// Read a `%` followed by a scope ID in base 10. |
266 | fn read_scope_id(&mut self) -> Option<u32> { |
267 | self.read_atomically(|p| { |
268 | p.read_given_char('%' )?; |
269 | p.read_number(10, None, true) |
270 | }) |
271 | } |
272 | |
273 | /// Read an IPv4 address with a port. |
274 | fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> { |
275 | self.read_atomically(|p| { |
276 | let ip = p.read_ipv4_addr()?; |
277 | let port = p.read_port()?; |
278 | Some(SocketAddrV4::new(ip, port)) |
279 | }) |
280 | } |
281 | |
282 | /// Read an IPv6 address with a port. |
283 | fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> { |
284 | self.read_atomically(|p| { |
285 | p.read_given_char('[' )?; |
286 | let ip = p.read_ipv6_addr()?; |
287 | let scope_id = p.read_scope_id().unwrap_or(0); |
288 | p.read_given_char(']' )?; |
289 | |
290 | let port = p.read_port()?; |
291 | Some(SocketAddrV6::new(ip, port, 0, scope_id)) |
292 | }) |
293 | } |
294 | |
295 | /// Read an IP address with a port |
296 | fn read_socket_addr(&mut self) -> Option<SocketAddr> { |
297 | self.read_socket_addr_v4() |
298 | .map(SocketAddr::V4) |
299 | .or_else(|| self.read_socket_addr_v6().map(SocketAddr::V6)) |
300 | } |
301 | } |
302 | |
303 | impl IpAddr { |
304 | /// Parse an IP address from a slice of bytes. |
305 | /// |
306 | /// ``` |
307 | /// #![feature(addr_parse_ascii)] |
308 | /// |
309 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
310 | /// |
311 | /// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); |
312 | /// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); |
313 | /// |
314 | /// assert_eq!(IpAddr::parse_ascii(b"127.0.0.1" ), Ok(localhost_v4)); |
315 | /// assert_eq!(IpAddr::parse_ascii(b"::1" ), Ok(localhost_v6)); |
316 | /// ``` |
317 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
318 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
319 | Parser::new(b).parse_with(|p| p.read_ip_addr(), kind:AddrKind::Ip) |
320 | } |
321 | } |
322 | |
323 | #[stable (feature = "ip_addr" , since = "1.7.0" )] |
324 | impl FromStr for IpAddr { |
325 | type Err = AddrParseError; |
326 | fn from_str(s: &str) -> Result<IpAddr, AddrParseError> { |
327 | Self::parse_ascii(s.as_bytes()) |
328 | } |
329 | } |
330 | |
331 | impl Ipv4Addr { |
332 | /// Parse an IPv4 address from a slice of bytes. |
333 | /// |
334 | /// ``` |
335 | /// #![feature(addr_parse_ascii)] |
336 | /// |
337 | /// use std::net::Ipv4Addr; |
338 | /// |
339 | /// let localhost = Ipv4Addr::new(127, 0, 0, 1); |
340 | /// |
341 | /// assert_eq!(Ipv4Addr::parse_ascii(b"127.0.0.1" ), Ok(localhost)); |
342 | /// ``` |
343 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
344 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
345 | // don't try to parse if too long |
346 | if b.len() > 15 { |
347 | Err(AddrParseError(AddrKind::Ipv4)) |
348 | } else { |
349 | Parser::new(b).parse_with(|p| p.read_ipv4_addr(), kind:AddrKind::Ipv4) |
350 | } |
351 | } |
352 | } |
353 | |
354 | #[stable (feature = "rust1" , since = "1.0.0" )] |
355 | impl FromStr for Ipv4Addr { |
356 | type Err = AddrParseError; |
357 | fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> { |
358 | Self::parse_ascii(s.as_bytes()) |
359 | } |
360 | } |
361 | |
362 | impl Ipv6Addr { |
363 | /// Parse an IPv6 address from a slice of bytes. |
364 | /// |
365 | /// ``` |
366 | /// #![feature(addr_parse_ascii)] |
367 | /// |
368 | /// use std::net::Ipv6Addr; |
369 | /// |
370 | /// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); |
371 | /// |
372 | /// assert_eq!(Ipv6Addr::parse_ascii(b"::1" ), Ok(localhost)); |
373 | /// ``` |
374 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
375 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
376 | Parser::new(b).parse_with(|p| p.read_ipv6_addr(), kind:AddrKind::Ipv6) |
377 | } |
378 | } |
379 | |
380 | #[stable (feature = "rust1" , since = "1.0.0" )] |
381 | impl FromStr for Ipv6Addr { |
382 | type Err = AddrParseError; |
383 | fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> { |
384 | Self::parse_ascii(s.as_bytes()) |
385 | } |
386 | } |
387 | |
388 | impl SocketAddrV4 { |
389 | /// Parse an IPv4 socket address from a slice of bytes. |
390 | /// |
391 | /// ``` |
392 | /// #![feature(addr_parse_ascii)] |
393 | /// |
394 | /// use std::net::{Ipv4Addr, SocketAddrV4}; |
395 | /// |
396 | /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); |
397 | /// |
398 | /// assert_eq!(SocketAddrV4::parse_ascii(b"127.0.0.1:8080" ), Ok(socket)); |
399 | /// ``` |
400 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
401 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
402 | Parser::new(b).parse_with(|p| p.read_socket_addr_v4(), kind:AddrKind::SocketV4) |
403 | } |
404 | } |
405 | |
406 | #[stable (feature = "socket_addr_from_str" , since = "1.5.0" )] |
407 | impl FromStr for SocketAddrV4 { |
408 | type Err = AddrParseError; |
409 | fn from_str(s: &str) -> Result<SocketAddrV4, AddrParseError> { |
410 | Self::parse_ascii(s.as_bytes()) |
411 | } |
412 | } |
413 | |
414 | impl SocketAddrV6 { |
415 | /// Parse an IPv6 socket address from a slice of bytes. |
416 | /// |
417 | /// ``` |
418 | /// #![feature(addr_parse_ascii)] |
419 | /// |
420 | /// use std::net::{Ipv6Addr, SocketAddrV6}; |
421 | /// |
422 | /// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0); |
423 | /// |
424 | /// assert_eq!(SocketAddrV6::parse_ascii(b"[2001:db8::1]:8080" ), Ok(socket)); |
425 | /// ``` |
426 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
427 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
428 | Parser::new(b).parse_with(|p| p.read_socket_addr_v6(), kind:AddrKind::SocketV6) |
429 | } |
430 | } |
431 | |
432 | #[stable (feature = "socket_addr_from_str" , since = "1.5.0" )] |
433 | impl FromStr for SocketAddrV6 { |
434 | type Err = AddrParseError; |
435 | fn from_str(s: &str) -> Result<SocketAddrV6, AddrParseError> { |
436 | Self::parse_ascii(s.as_bytes()) |
437 | } |
438 | } |
439 | |
440 | impl SocketAddr { |
441 | /// Parse a socket address from a slice of bytes. |
442 | /// |
443 | /// ``` |
444 | /// #![feature(addr_parse_ascii)] |
445 | /// |
446 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; |
447 | /// |
448 | /// let socket_v4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); |
449 | /// let socket_v6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080); |
450 | /// |
451 | /// assert_eq!(SocketAddr::parse_ascii(b"127.0.0.1:8080" ), Ok(socket_v4)); |
452 | /// assert_eq!(SocketAddr::parse_ascii(b"[::1]:8080" ), Ok(socket_v6)); |
453 | /// ``` |
454 | #[unstable (feature = "addr_parse_ascii" , issue = "101035" )] |
455 | pub fn parse_ascii(b: &[u8]) -> Result<Self, AddrParseError> { |
456 | Parser::new(b).parse_with(|p| p.read_socket_addr(), kind:AddrKind::Socket) |
457 | } |
458 | } |
459 | |
460 | #[stable (feature = "rust1" , since = "1.0.0" )] |
461 | impl FromStr for SocketAddr { |
462 | type Err = AddrParseError; |
463 | fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> { |
464 | Self::parse_ascii(s.as_bytes()) |
465 | } |
466 | } |
467 | |
468 | #[derive (Debug, Clone, PartialEq, Eq)] |
469 | enum AddrKind { |
470 | Ip, |
471 | Ipv4, |
472 | Ipv6, |
473 | Socket, |
474 | SocketV4, |
475 | SocketV6, |
476 | } |
477 | |
478 | /// An error which can be returned when parsing an IP address or a socket address. |
479 | /// |
480 | /// This error is used as the error type for the [`FromStr`] implementation for |
481 | /// [`IpAddr`], [`Ipv4Addr`], [`Ipv6Addr`], [`SocketAddr`], [`SocketAddrV4`], and |
482 | /// [`SocketAddrV6`]. |
483 | /// |
484 | /// # Potential causes |
485 | /// |
486 | /// `AddrParseError` may be thrown because the provided string does not parse as the given type, |
487 | /// often because it includes information only handled by a different address type. |
488 | /// |
489 | /// ```should_panic |
490 | /// use std::net::IpAddr; |
491 | /// let _foo: IpAddr = "127.0.0.1:8080" .parse().expect("Cannot handle the socket port" ); |
492 | /// ``` |
493 | /// |
494 | /// [`IpAddr`] doesn't handle the port. Use [`SocketAddr`] instead. |
495 | /// |
496 | /// ``` |
497 | /// use std::net::SocketAddr; |
498 | /// |
499 | /// // No problem, the `panic!` message has disappeared. |
500 | /// let _foo: SocketAddr = "127.0.0.1:8080" .parse().expect("unreachable panic" ); |
501 | /// ``` |
502 | #[stable (feature = "rust1" , since = "1.0.0" )] |
503 | #[derive (Debug, Clone, PartialEq, Eq)] |
504 | pub struct AddrParseError(AddrKind); |
505 | |
506 | #[stable (feature = "addr_parse_error_error" , since = "1.4.0" )] |
507 | impl fmt::Display for AddrParseError { |
508 | #[allow (deprecated, deprecated_in_future)] |
509 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
510 | fmt.write_str(self.description()) |
511 | } |
512 | } |
513 | |
514 | #[stable (feature = "addr_parse_error_error" , since = "1.4.0" )] |
515 | impl Error for AddrParseError { |
516 | #[allow (deprecated)] |
517 | fn description(&self) -> &str { |
518 | match self.0 { |
519 | AddrKind::Ip => "invalid IP address syntax" , |
520 | AddrKind::Ipv4 => "invalid IPv4 address syntax" , |
521 | AddrKind::Ipv6 => "invalid IPv6 address syntax" , |
522 | AddrKind::Socket => "invalid socket address syntax" , |
523 | AddrKind::SocketV4 => "invalid IPv4 socket address syntax" , |
524 | AddrKind::SocketV6 => "invalid IPv6 socket address syntax" , |
525 | } |
526 | } |
527 | } |
528 | |