58 lines · 2.3 KB · Rust
RawDownload
use gix_validate::submodule::name::Error; #[test]fn valid() {    fn validate(name: &str) -> Result<(), Error> {        gix_validate::submodule::name(name.into()).map(|_| ())    }     for valid_name in ["a/./b/..[", "..a/./b/", r"..a\./b\", "你好"] {        validate(valid_name).unwrap_or_else(|err| panic!("{valid_name} should be valid: {err:?}"));    }} mod invalid {    use bstr::ByteSlice;     macro_rules! mktest {        ($name:ident, $input:literal, $expected:ident) => {            #[test]            fn $name() {                match gix_validate::submodule::name($input.as_bstr()) {                    Err(gix_validate::submodule::name::Error::$expected) => {}                    got => panic!("Wanted {}, got {:?}", stringify!($expected), got),                }            }        };    }     mktest!(empty, b"", Empty);    mktest!(starts_with_parent_component, b"../", ParentComponent);    mktest!(parent_component_in_middle, b"hi/../ho", ParentComponent);    mktest!(ends_with_parent_component, b"hi/ho/..", ParentComponent);    mktest!(only_parent_component, b"..", ParentComponent);    mktest!(starts_with_parent_component_backslash, br"..\", ParentComponent);    mktest!(parent_component_in_middle_backslash, br"hi\..\ho", ParentComponent);    mktest!(ends_with_parent_component_backslash, br"hi\ho\..", ParentComponent);     /// Reproducer for GHSA-p3hw-mv63-rf9w: a crafted submodule name can place a harmless `..`    /// first and a real `../` traversal later, so validators that only inspect the first match    /// accept a name that still escapes `.git/modules`.    #[test]    fn traversal_after_a_benign_double_dot_is_rejected() {        match gix_validate::submodule::name(b"a..b/../../../.git/".as_bstr()) {            Err(gix_validate::submodule::name::Error::ParentComponent) => {}            got => panic!("Wanted ParentComponent, got {got:?}"),        }    }     /// Reproducer for GHSA-p3hw-mv63-rf9w: the same first-match bypass also applies to    /// Windows-style separators.    #[test]    fn backslash_traversal_after_a_benign_double_dot_is_rejected() {        match gix_validate::submodule::name(br"a..b\..\..\..\.git\".as_bstr()) {            Err(gix_validate::submodule::name::Error::ParentComponent) => {}            got => panic!("Wanted ParentComponent, got {got:?}"),        }    }}