Skip to content

Commit bfb0c96

Browse files
fix: nil pointer panic when framing an embedded @list value
The issue was identified where a nil pointer panic occurred during the framing process when handling embedded @list values. This fix ensures proper handling of such scenarios to prevent the application from crashing unexpectedly. Closes: #91 Co-authored-by: Alex Borodin <[email protected]> Signed-off-by: Alex Borodin <[email protected]> Signed-off-by: Michael Adler <[email protected]>
1 parent 4a395db commit bfb0c96

File tree

2 files changed

+131
-14
lines changed

2 files changed

+131
-14
lines changed

ld/api_frame.go

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -617,21 +617,18 @@ func removeEmbed(state *FramingContext, id string) {
617617
func removeDependents(embeds map[string]*EmbedNode, id string) {
618618
// get embed keys as a separate array to enable deleting keys in map
619619
for idDep, e := range embeds {
620-
var p map[string]interface{}
621-
if e.parent != nil {
622-
var isMap bool
623-
p, isMap = e.parent.(map[string]interface{})
624-
if !isMap {
625-
continue
626-
}
627-
} else {
628-
p = make(map[string]interface{})
620+
if e.parent == nil {
621+
continue
629622
}
630-
631-
pid := p["@id"].(string)
632-
if id == pid {
633-
delete(embeds, idDep)
634-
removeDependents(embeds, idDep)
623+
p, isMap := e.parent.(map[string]interface{})
624+
if !isMap {
625+
continue
626+
}
627+
if pid, hasID := p["@id"]; hasID {
628+
if id == pid.(string) {
629+
delete(embeds, idDep)
630+
removeDependents(embeds, idDep)
631+
}
635632
}
636633
}
637634
}

ld/api_frame_test.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
package ld_test
1616

1717
import (
18+
"encoding/json"
1819
"testing"
1920

2021
. "github.com/piprate/json-gold/ld"
2122
"github.com/stretchr/testify/assert"
23+
"github.com/stretchr/testify/require"
2224
)
2325

2426
func TestGetFrameFlag(t *testing.T) {
@@ -76,3 +78,121 @@ func TestGetFrameFlag(t *testing.T) {
7678
),
7779
)
7880
}
81+
82+
func TestJsonLdApi_Frame(t *testing.T) {
83+
var input any
84+
err := json.Unmarshal([]byte(shaclValidationResult), &input)
85+
require.NoError(t, err)
86+
var frame any
87+
err = json.Unmarshal([]byte(shaclValidationResultFrame), &frame)
88+
require.NoError(t, err)
89+
framed, err := NewJsonLdProcessor().Frame(input, frame, nil)
90+
require.NoError(t, err)
91+
assert.Equal(t, []any{map[string]any{
92+
"sh:resultPath": "https://example.com/hasScrewable",
93+
"sh:sourceShape": map[string]any{
94+
"sh:or": map[string]any{
95+
"@list": []any{
96+
map[string]any{
97+
"sh:class": "https://example.com/Bolt",
98+
"type": "sh:NodeShape",
99+
},
100+
map[string]any{
101+
"sh:class": "https://example.com/Screw",
102+
"type": "sh:NodeShape",
103+
},
104+
},
105+
},
106+
"sh:path": "https://example.com/hasScrewable",
107+
"type": "sh:PropertyShape",
108+
},
109+
"type": "sh:ValidationResult",
110+
}}, framed["@graph"])
111+
}
112+
113+
const shaclValidationResult = `
114+
[
115+
{
116+
"@id": "_:ccbca2cd103643858f1087647dd5399717617",
117+
"@type": [
118+
"http://www.w3.org/ns/shacl#ValidationResult"
119+
],
120+
"http://www.w3.org/ns/shacl#resultPath": [
121+
{
122+
"@id": "https://example.com/hasScrewable"
123+
}
124+
],
125+
"http://www.w3.org/ns/shacl#sourceShape": [
126+
{
127+
"@id": "_:node94090"
128+
}
129+
]
130+
},
131+
{
132+
"@id": "_:node94090",
133+
"@type": [
134+
"http://www.w3.org/ns/shacl#PropertyShape"
135+
],
136+
"http://www.w3.org/ns/shacl#or": [
137+
{
138+
"@list": [
139+
{
140+
"@id": "_:node94092"
141+
},
142+
{
143+
"@id": "_:node94094"
144+
}
145+
]
146+
}
147+
],
148+
"http://www.w3.org/ns/shacl#path": [
149+
{
150+
"@id": "https://example.com/hasScrewable"
151+
}
152+
]
153+
},
154+
{
155+
"@id": "_:node94092",
156+
"@type": [
157+
"http://www.w3.org/ns/shacl#NodeShape"
158+
],
159+
"http://www.w3.org/ns/shacl#class": [
160+
{
161+
"@id": "https://example.com/Bolt"
162+
}
163+
]
164+
},
165+
{
166+
"@id": "_:node94094",
167+
"@type": [
168+
"http://www.w3.org/ns/shacl#NodeShape"
169+
],
170+
"http://www.w3.org/ns/shacl#class": [
171+
{
172+
"@id": "https://example.com/Screw"
173+
}
174+
]
175+
}
176+
]`
177+
178+
const shaclValidationResultFrame = `{
179+
"@context": {
180+
"sh": "http://www.w3.org/ns/shacl#",
181+
"sh:resultPath": {
182+
"@id": "sh:resultPath",
183+
"@type": "@id"
184+
},
185+
"sh:path": {
186+
"@id": "sh:path",
187+
"@type": "@id"
188+
},
189+
"sh:class": {
190+
"@id": "sh:class",
191+
"@type": "@id"
192+
},
193+
"type": "@type",
194+
"value": "@value",
195+
"id": "@id"
196+
},
197+
"@type": "sh:ValidationResult"
198+
}`

0 commit comments

Comments
 (0)