From e93a60dea1d2f06aedaaf9ce4a83cd3324ef7574 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Mon, 26 Aug 2024 21:27:56 -0600 Subject: [PATCH] prevent oob --- d2compiler/compile_test.go | 11 ++ d2ir/compile.go | 4 + .../link-beyond-import-root.exp.json | 114 ++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 testdata/d2compiler/TestCompile/link-beyond-import-root.exp.json diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 06e2c67fe1..fc347fc10d 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2386,6 +2386,17 @@ layers: { tassert.Equal(t, "root.layers.a", g.Layers[2].Layers[0].Objects[2].Link.Value) }, }, + { + name: "link-beyond-import-root", + text: `...@x`, + files: map[string]string{ + "x.d2": `x.link: _.layers.z +`, + }, + assertions: func(t *testing.T, g *d2graph.Graph) { + tassert.Equal(t, (*d2graph.Scalar)(nil), g.Objects[0].Link) + }, + }, { name: "link-board-underscore-not-found", text: `x diff --git a/d2ir/compile.go b/d2ir/compile.go index 8f8a16ca02..85432710b6 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -904,6 +904,7 @@ func (c *compiler) ignoreLazyGlob(n Node) bool { func (c *compiler) extendLinks(m *Map, importF *Field, importDir string) { nodeBoardKind := NodeBoardKind(m) importIDA := IDA(importF) +FIELDS_LOOP: for _, f := range m.Fields { if f.Name == "link" { if nodeBoardKind != "" { @@ -922,6 +923,9 @@ func (c *compiler) extendLinks(m *Map, importF *Field, importDir string) { for _, id := range linkIDA[1:] { if id == "_" { + if len(linkIDA) < 2 || len(importIDA) < 2 { + continue FIELDS_LOOP + } linkIDA = append([]string{linkIDA[0]}, linkIDA[2:]...) importIDA = importIDA[:len(importIDA)-2] } else { diff --git a/testdata/d2compiler/TestCompile/link-beyond-import-root.exp.json b/testdata/d2compiler/TestCompile/link-beyond-import-root.exp.json new file mode 100644 index 0000000000..36ee7d8dfc --- /dev/null +++ b/testdata/d2compiler/TestCompile/link-beyond-import-root.exp.json @@ -0,0 +1,114 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile/link-beyond-import-root.d2,0:0:0-0:5:5", + "nodes": [ + { + "import": { + "range": "d2/testdata/d2compiler/TestCompile/link-beyond-import-root.d2,0:0:0-0:5:5", + "spread": true, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/link-beyond-import-root.d2,0:4:4-0:5:5", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/x.d2,0:0:0-0:6:6", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/x.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/x.d2,0:2:2-0:6:6", + "value": [ + { + "string": "link", + "raw_string": "link" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +}