@@ -699,7 +699,6 @@ func TestValidatePathEntry_UNC(t *testing.T) {
699699}
700700
701701func TestValidatePathEntry_NTFSADS (t * testing.T ) {
702- // foo:bar — NTFS alternate data stream syntax.
703702 assert .NotEmpty (t , validatePathEntry ("foo:bar" , false ))
704703 assert .NotEmpty (t , validatePathEntry ("dir/foo:bar.txt" , false ))
705704}
@@ -714,7 +713,6 @@ func TestValidatePathEntry_ReservedDeviceNames(t *testing.T) {
714713}
715714
716715func TestValidatePathEntry_ReservedDeviceNames_NotMatchedAsSubstring (t * testing.T ) {
717- // CONSOLE / NULLABLE are not reserved device names.
718716 for _ , p := range []string {"CONSOLE.md" , "NULLABLE" , "COMPANY" , "LPT10" } {
719717 assert .Empty (t , validatePathEntry (p , false ), "path %q should be accepted" , p )
720718 }
@@ -733,34 +731,34 @@ func TestValidatePathEntry_Tilde(t *testing.T) {
733731}
734732
735733func TestValidatePathEntry_DotDot (t * testing.T ) {
736- // A path that escapes root after Clean (or is "..") is rejected.
737734 for _ , p := range []string {"../out.png" , ".." , "a/../../b.png" } {
738735 assert .NotEmpty (t , validatePathEntry (p , false ), "path %q should be rejected" , p )
739736 }
740737}
741738
742739func TestValidatePathEntry_InteriorDotDotThatCleansInBounds (t * testing.T ) {
743- // Per the plan's path-shape rule, the check is on the result of
744- // path.Clean: "a/../b.png" cleans to "b.png", which stays in-root,
745- // so it is accepted.
740+ // "a/../b.png" cleans to "b.png" (stays in-root), so it is accepted.
746741 assert .Empty (t , validatePathEntry ("a/../b.png" , false ))
747742}
748743
744+ func TestValidatePathEntry_DotDotCollapsesToRoot (t * testing.T ) {
745+ // "a/.." cleans to "." (workspace root) — reject to prevent artifacts at ".".
746+ assert .NotEmpty (t , validatePathEntry ("a/.." , false ))
747+ }
748+
749749func TestValidatePathEntry_UnderMdsmithDir (t * testing.T ) {
750750 for _ , p := range []string {".mdsmith/state" , ".mdsmith/out.png" } {
751751 assert .NotEmpty (t , validatePathEntry (p , false ), "path %q should be rejected" , p )
752752 }
753753}
754754
755755func TestValidatePathEntry_OutputsRejectGlobChars (t * testing.T ) {
756- // allowGlob=false: glob meta-characters are rejected.
757- for _ , p := range []string {"out*.png" , "out?.png" , "out[1].png" } {
756+ for _ , p := range []string {"out*.png" , "out?.png" , "out[1].png" , "out{a,b}.png" } {
758757 assert .NotEmpty (t , validatePathEntry (p , false ), "path %q should be rejected for outputs" , p )
759758 }
760759}
761760
762761func TestValidatePathEntry_InputsAcceptGlobChars (t * testing.T ) {
763- // allowGlob=true: doublestar globs are accepted.
764762 for _ , p := range []string {
765763 "src/*.md" , "**/*.md" , "chapters/[0-9]*.md" , "a?b.md" , "{a,b}.md" ,
766764 } {
0 commit comments