aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 22:31:12 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 22:31:12 +0200
commita91b713dcec4d17f76155f0cd6b26903c59b9c19 (patch)
tree44b1354e152c71a978738ee6ec47164ccef10b81 /internal
parentc03a72f1d7b598c1fe8fd01bb1f5bbfbd0256313 (diff)
downloadkrino-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.go8
-rw-r--r--internal/config/skel_test.go3
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 {