this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cue/interpreter/embed: respect module boundaries

The embed proposal specifies that it should not be possible
to embed files across module boundaries. This CL
implements that restriction.

Also fix in passing an unnecessarily broad "is parent directory"
check: it's OK for a file to start with two dots.

Fixes #3273.

Signed-off-by: Roger Peppe <rogpeppe@gmail.com>
Change-Id: I4e80edcc49f5d6475ccdd3f46d206e46be55723b
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1197383
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>

+45 -27
+12 -25
cmd/cue/cmd/testdata/script/embed.txtar
··· 35 35 // These are all valid. 36 36 underscoreFile: _ @embed(file="y/_test.json") 37 37 dotFile: _ @embed(file="y/.test.json") 38 + dotdotFile: _ @embed(file="..dotdot.json") 38 39 underscoreDir: _ @embed(file="_y/test.json") 39 40 dotDir: _ @embed(file=".y/test.json") 40 - 41 - // TODO: fix nested modules are currently not supported, but we may opt to 42 - // support them in the future. This is currently not handled. It should 43 - // probably be up to the loader to provide a fs.FS that handles this 44 - // according to spec. 45 - nestedModJSON: _ @embed(file="a/b/foo.json") 46 41 } 47 42 48 43 -- test.json -- 49 44 { "x": 34 } 50 45 -- input.yaml -- 51 46 a1: 2 52 - 47 + -- ..dotdot.json -- 48 + {"dotdot": true} 53 49 -- y/test.json -- 54 50 { "x": 34 } 55 51 -- y/_test.json -- ··· 121 117 special: { 122 118 underscoreFile: _ 123 119 dotFile: _ 120 + dotdotFile: _ 124 121 underscoreDir: _ 125 122 dotDir: _ 126 - nestedModJSON: _ 127 123 } 128 124 -- out/eval -- 129 125 a: { ··· 208 204 dotFile: { 209 205 z: 46 210 206 } 207 + dotdotFile: { 208 + dotdot: true 209 + } 211 210 underscoreDir: { 212 211 z: 47 213 212 } 214 213 dotDir: { 215 214 z: 48 216 - } 217 - nestedModJSON: { 218 - a: 1 219 - b: 2 220 215 } 221 216 } 222 217 -- out/export -- ··· 265 260 } 266 261 special: { 267 262 // These are all valid. 268 - underscoreFile: z: 45 269 - dotFile: z: 46 270 - underscoreDir: z: 47 271 - dotDir: z: 48 272 - 273 - // TODO: fix nested modules are currently not supported, but we may opt to 274 - // support them in the future. This is currently not handled. It should 275 - // probably be up to the loader to provide a fs.FS that handles this 276 - // according to spec. 277 - nestedModJSON: { 278 - a: 1 279 - b: 2 280 - } 263 + underscoreFile: z: 45 264 + dotFile: z: 46 265 + dotdotFile: dotdot: true 266 + underscoreDir: z: 47 267 + dotDir: z: 48 281 268 } 282 269 -- out/vet --
+12
cmd/cue/cmd/testdata/script/embed_err.txtar
··· 56 56 unspecifiedFiletype3: _ @embed(glob=x/*.?son) 57 57 unspecifiedFiletype4: _ @embed(glob=x/*.[j]son) 58 58 59 + nestedModJSON: _ @embed(file="a/b/foo.json") 60 + nestedModJSONWithGlob: _ @embed(glob="a/*/*.json") 61 + 59 62 -- test.json -- 60 63 { "x": 34 } 61 64 -- test.ldjson -- ··· 80 83 x: 5 81 84 -- xcue -- 82 85 x: 5 86 + -- a/b/cue.mod/modules.cue -- 87 + module: "acme.com" 88 + language: version: "v0.9.0" 89 + -- a/b/foo.json -- 90 + {"a": 1, "b": 2} 83 91 -- out/std -- 84 92 -- out/err -- 85 93 @embed: attribute must have file or glob field: ··· 130 138 ./test.cue:49:25 131 139 @embed: extension not fully specified; type argument required: 132 140 ./test.cue:50:25 141 + @embed: cannot embed file "a/b/foo.json": in different module: 142 + ./test.cue:52:18 143 + @embed: cannot embed file "a/b/foo.json": in different module: 144 + ./test.cue:53:26
+21 -2
cue/interpreter/embed/embed.go
··· 202 202 if err != nil { 203 203 return nil, err 204 204 } 205 + for dir := path.Dir(file); dir != "."; dir = path.Dir(dir) { 206 + if _, err := c.fs.Stat(path.Join(dir, "cue.mod")); err == nil { 207 + return nil, errors.Newf(c.pos, "cannot embed file %q: in different module", file) 208 + } 209 + } 205 210 206 211 return c.decodeFile(file, scope, schema) 207 212 } ··· 233 238 return nil, errors.Promote(err, "failed to match glob") 234 239 } 235 240 241 + dirs := make(map[string]string) 236 242 for _, f := range matches { 237 243 // TODO: lots of stat calls happening in this MVP so another won't hurt. 238 244 // We don't support '**' initially, and '*' only matches files, so skip ··· 242 248 } else if fi.IsDir() { 243 249 continue 244 250 } 251 + // Add all parents of the embedded file that 252 + // aren't the current directory (if there's a cue.mod 253 + // in the current directory, that's the current module 254 + // not nested). 255 + for dir := path.Dir(f); dir != "."; dir = path.Dir(dir) { 256 + dirs[dir] = f 257 + } 245 258 246 259 expr, err := c.decodeFile(f, scope, schema) 247 260 if err != nil { ··· 253 266 Value: expr, 254 267 }) 255 268 } 256 - 269 + // Check that none of the matches were in a nested module 270 + // directory. 271 + for dir, f := range dirs { 272 + if _, err := c.fs.Stat(path.Join(dir, "cue.mod")); err == nil { 273 + return nil, errors.Newf(c.pos, "cannot embed file %q: in different module", f) 274 + } 275 + } 257 276 return m, nil 258 277 } 259 278 ··· 265 284 if path.IsAbs(file) { 266 285 return "", errors.Newf(c.pos, "only relative files are allowed") 267 286 } 268 - if strings.HasPrefix(file, "..") { 287 + if file == ".." || strings.HasPrefix(file, "../") { 269 288 return "", errors.Newf(c.pos, "cannot refer to parent directory") 270 289 } 271 290 return file, nil