diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-14 22:31:12 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-14 22:31:12 +0200 |
| commit | a91b713dcec4d17f76155f0cd6b26903c59b9c19 (patch) | |
| tree | 44b1354e152c71a978738ee6ec47164ccef10b81 /internal | |
| parent | c03a72f1d7b598c1fe8fd01bb1f5bbfbd0256313 (diff) | |
| download | krino-a91b713dcec4d17f76155f0cd6b26903c59b9c19.tar.gz krino-a91b713dcec4d17f76155f0cd6b26903c59b9c19.zip | |
plan 10: stderr messages cannot be split by quoted newlines; config paths escaped; krino new refuses control characters; independent terminal oracle
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/config/skel.go | 8 | ||||
| -rw-r--r-- | internal/config/skel_test.go | 3 |
2 files changed, 10 insertions, 1 deletions
diff --git a/internal/config/skel.go b/internal/config/skel.go index ca914e3..2e54894 100644 --- a/internal/config/skel.go +++ b/internal/config/skel.go @@ -10,6 +10,7 @@ import ( "io/fs" "os" "path/filepath" + "unicode" "unicode/utf8" "krino/internal/sexp" @@ -72,6 +73,13 @@ func NewDir(mainFile, name, path string) (string, error) { if !utf8.ValidString(abs) { return "", fmt.Errorf("%q is not valid UTF-8; krino's config is UTF-8 text, so rename the directory first", abs) } + // Nor control or bidirectional characters: a directory unpacked from a + // download could name itself with escape codes (re-review cli F1). + for _, r := range abs { + if unicode.IsControl(r) || unicode.Is(unicode.Bidi_Control, r) || unicode.In(r, unicode.Zl, unicode.Zp) { + return "", fmt.Errorf("%q holds control or bidirectional characters; rename the directory first", abs) + } + } if fi, err := os.Stat(abs); err != nil || !fi.IsDir() { return "", fmt.Errorf("%s is not a directory", abs) } diff --git a/internal/config/skel_test.go b/internal/config/skel_test.go index 3815336..4e2e802 100644 --- a/internal/config/skel_test.go +++ b/internal/config/skel_test.go @@ -243,7 +243,7 @@ func TestNewDirErrors(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) writeFiles(t, home, map[string]string{ - "krino.conf": `(include "a")`, "dirs/a.conf": `(path "~")`, "x/.keep": "", "f": "", "lat\xe9n/.keep": "", + "krino.conf": `(include "a")`, "dirs/a.conf": `(path "~")`, "x/.keep": "", "f": "", "lat\xe9n/.keep": "", "ctl\x1bx/.keep": "", }) main := filepath.Join(home, "krino.conf") tests := []struct{ name, path, want string }{ @@ -253,6 +253,7 @@ func TestNewDirErrors(t *testing.T) { {"b", "~/missing", filepath.Join(home, "missing") + " is not a directory"}, {"a", "~/x", `"a" is already included`}, {"b", "~/lat\xe9n", fmt.Sprintf("%q is not valid UTF-8; krino's config is UTF-8 text, so rename the directory first", filepath.Join(home, "lat\xe9n"))}, + {"b", "~/ctl\x1bx", fmt.Sprintf("%q holds control or bidirectional characters; rename the directory first", filepath.Join(home, "ctl\x1bx"))}, } for _, tt := range tests { if _, err := NewDir(main, tt.name, tt.path); err == nil || err.Error() != tt.want { |
