From 187fb1a3b08d4bcbf14be755a1981352fcac0b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Wed, 31 Jul 2024 12:11:51 +0100 Subject: [PATCH] cue/interpreter/embed: forbid `**` via pkg/path.Match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our pkg/path.Match func mimics Go's own path.Match in that it can be used as a validator via `Match(pattern, "")`. This is better than a `strings.Contains(pattern, "**")` not only because we get consistent error messages, but also because Contains gives false positives on valid patterns such as `\**`, which escapes the first star, or `[x**y]`, where the stars are just part of a character set. Fix the code, and add more tests that demonstrate that embedding does support a glob with `\**` now. This brings embed in line with pkg/path.Match and tool/file.Glob in terms of what pattern matching syntax and features it supports. Signed-off-by: Daniel Martí Change-Id: I0ed6fcab9426c6392fb18491a3f656f29c56b41e Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1198692 Reviewed-by: Roger Peppe Unity-Result: CUE porcuepine TryBot-Result: CUEcueckoo --- cmd/cue/cmd/testdata/script/embed_err.txtar | 2 +- .../cmd/testdata/script/embed_windows.txtar | 33 +++++++++++++++++++ cue/interpreter/embed/embed.go | 7 ++-- 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 cmd/cue/cmd/testdata/script/embed_windows.txtar diff --git a/cmd/cue/cmd/testdata/script/embed_err.txtar b/cmd/cue/cmd/testdata/script/embed_err.txtar index 3f35b96da2b..0054b587b46 100644 --- a/cmd/cue/cmd/testdata/script/embed_err.txtar +++ b/cmd/cue/cmd/testdata/script/embed_err.txtar @@ -106,7 +106,7 @@ language: version: "v0.9.0" ./test.cue:19:15 @embed: only relative files are allowed: ./test.cue:21:12 -@embed: double star not (yet) supported in glob: +@embed: invalid glob pattern "**/*.json": '**' is not supported in patterns as of yet: ./test.cue:23:15 @embed: streaming not implemented: found more than one value in file: ./test.cue:25:11 diff --git a/cmd/cue/cmd/testdata/script/embed_windows.txtar b/cmd/cue/cmd/testdata/script/embed_windows.txtar new file mode 100644 index 00000000000..5f2310944ac --- /dev/null +++ b/cmd/cue/cmd/testdata/script/embed_windows.txtar @@ -0,0 +1,33 @@ +env CUE_EXPERIMENT=embed + +[!windows] cp reuse.json 'star/*.json' +[!windows] exec cue export --out cue +[!windows] cmp stdout out/export-unix + +[windows] exec cue export --out cue +[windows] cmp stdout out/export-windows + +-- test.cue -- +@extern(embed) + +package foo + +// Unix OSes can have a file containing a star character, and we can match it. +// Windows can still use these file paths and glob patterns, but they can't match +// a file containing a star character, as such filenames are not allowed on Windows. + +globStar: _ @embed(glob="star/*.json") +globEscapeStar: _ @embed(glob="star/\\**", type=json) +-- reuse.json -- +{"x": "to be reused for more names"} +-- star/simple.json -- +{"x": "does not contain a star character"} +-- out/export-unix -- +globStar: { + "star/*.json": x: "to be reused for more names" + "star/simple.json": x: "does not contain a star character" +} +globEscapeStar: "star/*.json": x: "to be reused for more names" +-- out/export-windows -- +globStar: "star/simple.json": x: "does not contain a star character" +globEscapeStar: {} diff --git a/cue/interpreter/embed/embed.go b/cue/interpreter/embed/embed.go index b1baf28cb30..90dbb704dcb 100644 --- a/cue/interpreter/embed/embed.go +++ b/cue/interpreter/embed/embed.go @@ -100,6 +100,7 @@ import ( "cuelang.org/go/internal/encoding" "cuelang.org/go/internal/filetypes" "cuelang.org/go/internal/value" + pkgpath "cuelang.org/go/pkg/path" ) // TODO: obtain a fs.FS from load or something similar @@ -218,8 +219,10 @@ func (c *compiler) processGlob(glob, scope string, schema adt.Value) (adt.Expr, return nil, ce } - if strings.Contains(glob, "**") { - return nil, errors.Newf(c.pos, "double star not (yet) supported in glob") + // Validate that the glob pattern is valid per [pkgpath.Match]. + // Note that we use Unix match semantics because all embed paths are Unix-like. + if _, err := pkgpath.Match(glob, "", pkgpath.Unix); err != nil { + return nil, errors.Wrapf(err, c.pos, "invalid glob pattern %q", glob) } // If we do not have a type, ensure the extension of the base is fully