Skip to content

Commit d230e0f

Browse files
committed
fix(parquet): RestoreNonColumnFields skips non-string tags instead of panicking
The tags-restore loop used an unchecked v.(string), so a stored extras tags array with a non-string element ({"tags":[42]} or a null, from arbitrary producer JSON / a backfilled bundle) panicked. The parquet Decode path has no recover, so this crashed the reader/backfill. Comma-ok the element assertion: skip non-strings, keep strings in order. Identical for well-formed input. Regression test added.
1 parent ef72990 commit d230e0f

2 files changed

Lines changed: 29 additions & 3 deletions

File tree

field_accessors.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,15 @@ func RestoreNonColumnFields(event *CloudEventHeader) {
2929
}
3030
if val, ok := event.Extras["tags"]; ok {
3131
if anySlice, ok := val.([]any); ok {
32-
typedSlice := make([]string, len(anySlice))
33-
for i, v := range anySlice {
34-
typedSlice[i] = v.(string)
32+
// Skip non-string elements rather than panic on the unchecked assertion:
33+
// stored extras come from arbitrary producer JSON (e.g. a backfilled bundle
34+
// with {"tags":[42]} or a null element), and the parquet Decode path has no
35+
// recover — an unguarded v.(string) would crash the reader/backfill.
36+
typedSlice := make([]string, 0, len(anySlice))
37+
for _, v := range anySlice {
38+
if s, ok := v.(string); ok {
39+
typedSlice = append(typedSlice, s)
40+
}
3541
}
3642
event.Tags = typedSlice
3743
}

field_accessors_panic_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package cloudevent
2+
3+
import "testing"
4+
5+
// TestRestoreNonColumnFields_MalformedTags: a stored tags array with non-string
6+
// elements (arbitrary producer JSON / a backfilled bundle) must not panic. Non-string
7+
// elements are skipped; strings are kept in order. Before the fix the unchecked
8+
// v.(string) panicked on the parquet Decode path, which has no recover.
9+
func TestRestoreNonColumnFields_MalformedTags(t *testing.T) {
10+
hdr := &CloudEventHeader{
11+
Extras: map[string]any{"tags": []any{"ok", float64(42), nil, "two", true}},
12+
}
13+
RestoreNonColumnFields(hdr) // must not panic
14+
if len(hdr.Tags) != 2 || hdr.Tags[0] != "ok" || hdr.Tags[1] != "two" {
15+
t.Fatalf("expected [ok two], got %v", hdr.Tags)
16+
}
17+
if _, stillThere := hdr.Extras["tags"]; stillThere {
18+
t.Error("tags should be deleted from Extras after restore")
19+
}
20+
}

0 commit comments

Comments
 (0)