1 1 | // Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
|
2 2 | /*
|
3 3 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
4 4 | * SPDX-License-Identifier: Apache-2.0
|
5 5 | */
|
6 6 |
|
7 7 | use crate::endpoint_lib::diagnostic::DiagnosticCollector;
|
8 8 |
|
9 9 | pub(crate) fn is_valid_host_label(label: &str, allow_dots: bool, e: &mut DiagnosticCollector) -> bool {
|
10 + | let bytes = label.as_bytes();
|
10 11 | if allow_dots {
|
11 - | for part in label.split('.') {
|
12 - | if !is_valid_host_label(part, false, e) {
|
12 + | let mut start = 0;
|
13 + | for i in 0..bytes.len() {
|
14 + | if bytes[i] == b'.' {
|
15 + | if !is_valid_segment(bytes, start, i, e) {
|
13 16 | return false;
|
14 17 | }
|
18 + | start = i + 1;
|
15 19 | }
|
16 - | true
|
20 + | }
|
21 + | is_valid_segment(bytes, start, bytes.len(), e)
|
17 22 | } else {
|
18 - | if label.is_empty() || label.len() > 63 {
|
23 + | is_valid_segment(bytes, 0, bytes.len(), e)
|
24 + | }
|
25 + | }
|
26 + |
|
27 + | #[inline]
|
28 + | fn is_valid_segment(bytes: &[u8], start: usize, end: usize, e: &mut DiagnosticCollector) -> bool {
|
29 + | let len = end - start;
|
30 + | if len == 0 || len > 63 {
|
19 31 | e.report_error("host was too short or too long");
|
20 32 | return false;
|
21 33 | }
|
22 - | label.chars().enumerate().all(|(idx, ch)| match (ch, idx) {
|
23 - | ('-', 0) => {
|
34 + | if bytes[start] == b'-' {
|
24 35 | e.report_error("cannot start with `-`");
|
25 - | false
|
36 + | return false;
|
26 37 | }
|
27 - | _ => ch.is_alphanumeric() || ch == '-',
|
28 - | })
|
38 + | for &b in &bytes[start..end] {
|
39 + | if !b.is_ascii_alphanumeric() && b != b'-' {
|
40 + | return false;
|
29 41 | }
|
42 + | }
|
43 + | true
|
30 44 | }
|
31 45 |
|
32 46 | #[cfg(all(test, feature = "gated-tests"))]
|
33 47 | mod test {
|
34 48 | use proptest::proptest;
|
35 49 |
|
36 50 | fn is_valid_host_label(label: &str, allow_dots: bool) -> bool {
|
37 51 | super::is_valid_host_label(label, allow_dots, &mut DiagnosticCollector::new())
|
38 52 | }
|
39 53 |
|
40 54 | #[allow(clippy::bool_assert_comparison)]
|
41 55 | #[test]
|
42 56 | fn basic_cases() {
|
43 57 | assert_eq!(is_valid_host_label("", false), false);
|
44 58 | assert_eq!(is_valid_host_label("", true), false);
|
45 59 | assert_eq!(is_valid_host_label(".", true), false);
|
46 60 | assert_eq!(is_valid_host_label("a.b", true), true);
|
47 61 | assert_eq!(is_valid_host_label("a.b", false), false);
|
48 62 | assert_eq!(is_valid_host_label("a.b.", true), false);
|
49 63 | assert_eq!(is_valid_host_label("a.b.c", true), true);
|
50 64 | assert_eq!(is_valid_host_label("a_b", true), false);
|
51 65 | assert_eq!(is_valid_host_label(&"a".repeat(64), false), false);
|
52 66 | assert_eq!(is_valid_host_label(&format!("{}.{}", "a".repeat(63), "a".repeat(63)), true), true);
|
53 67 | }
|
54 68 |
|
55 69 | #[allow(clippy::bool_assert_comparison)]
|
56 70 | #[test]
|
57 71 | fn start_bounds() {
|
58 72 | assert_eq!(is_valid_host_label("-foo", false), false);
|
59 73 | assert_eq!(is_valid_host_label("-foo", true), false);
|
60 74 | assert_eq!(is_valid_host_label(".foo", true), false);
|
61 75 | assert_eq!(is_valid_host_label("a-b.foo", true), true);
|
62 76 | }
|
63 77 |
|
78 + | #[allow(clippy::bool_assert_comparison)]
|
79 + | #[test]
|
80 + | fn non_ascii_rejected() {
|
81 + | // DNS host labels only allow ASCII alphanumeric and hyphens (RFC 952/1123)
|
82 + | assert_eq!(is_valid_host_label("café", false), false);
|
83 + | assert_eq!(is_valid_host_label("bücher", false), false);
|
84 + | assert_eq!(is_valid_host_label("日本語", false), false);
|
85 + | assert_eq!(is_valid_host_label("a.café.b", true), false);
|
86 + | assert_eq!(is_valid_host_label("🚀rocket", false), false);
|
87 + | // ASCII is fine
|
88 + | assert_eq!(is_valid_host_label("abc123", false), true);
|
89 + | assert_eq!(is_valid_host_label("a-b-c", false), true);
|
90 + | }
|
91 + |
|
64 92 | use crate::endpoint_lib::diagnostic::DiagnosticCollector;
|
65 93 | use proptest::prelude::*;
|
66 94 | proptest! {
|
67 95 | #[test]
|
68 96 | fn no_panics(s in any::<String>(), dots in any::<bool>()) {
|
69 97 | is_valid_host_label(&s, dots);
|
70 98 | }
|
71 99 | }
|
72 100 | }
|