Skip to content

Commit fef722d

Browse files
MB-65807: Graceful handling of non-conforming polygon data (#2166)
Geo's `extract3DCoordinates` does not validate input data which can cause malformed polygon data to cause a panic: ``` panic: reflect: call of reflect.Value.Index on map Value panic({0x100a9e0c0?, 0x140001163a8?}) /opt/homebrew/opt/go/libexec/src/runtime/panic.go:770 +0x124 reflect.Value.Index({0x100a9ffe0?, 0x14000118c00?, 0x14000062c58?}, 0x1008913c8?) /opt/homebrew/opt/go/libexec/src/reflect/value.go:1447 +0x170 github.com/blevesearch/bleve/v2/geo.extract3DCoordinates({0x100a9ffe0?, 0x14000118c00?}) /Users/abhinav.dangeti/Documents/go/src/github.com/blevesearch/bleve/geo/parse.go:245 +0x12c github.com/blevesearch/bleve/v2/geo.ExtractGeoShapeCoordinates({0x100a9ffe0?, 0x14000118c00?}, {0x100a24659, 0x7}) ``` See: https://pkg.go.dev/reflect#Value.IsValid
1 parent a20efc1 commit fef722d

File tree

2 files changed

+114
-9
lines changed

2 files changed

+114
-9
lines changed

geo/parse.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -236,14 +236,19 @@ func extract2DCoordinates(thing interface{}) [][]float64 {
236236

237237
func extract3DCoordinates(thing interface{}) (c [][][]float64) {
238238
coords := reflect.ValueOf(thing)
239-
for i := 0; i < coords.Len(); i++ {
240-
vals := coords.Index(i)
241-
242-
edges := vals.Interface()
243-
if es, ok := edges.([]interface{}); ok {
244-
loop := extract2DCoordinates(es)
245-
if len(loop) > 0 {
246-
c = append(c, loop)
239+
if !coords.IsValid() {
240+
return nil
241+
}
242+
243+
if coords.Kind() == reflect.Slice {
244+
for i := 0; i < coords.Len(); i++ {
245+
vals := coords.Index(i)
246+
edges := vals.Interface()
247+
if es, ok := edges.([]interface{}); ok {
248+
loop := extract2DCoordinates(es)
249+
if len(loop) > 0 {
250+
c = append(c, loop)
251+
}
247252
}
248253
}
249254
}

geo/parse_test.go

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
package geo
1616

1717
import (
18+
"encoding/json"
1819
"reflect"
1920
"testing"
2021
)
2122

2223
func TestExtractGeoPoint(t *testing.T) {
23-
2424
tests := []struct {
2525
in interface{}
2626
lon float64
@@ -353,3 +353,103 @@ func TestExtractGeoShape(t *testing.T) {
353353
}
354354
}
355355
}
356+
357+
func TestExtractGeoShapeCoordinates(t *testing.T) {
358+
tests := []struct {
359+
x []byte
360+
typ string
361+
expectOK bool
362+
}{
363+
{
364+
x: []byte(`[
365+
[
366+
[77.58894681930542,12.976498523818783],
367+
[77.58677959442139,12.974533005048169],
368+
[77.58894681930542,12.976498523818783]
369+
]
370+
]`),
371+
typ: PolygonType,
372+
expectOK: true,
373+
},
374+
{ // Invalid construct, but handled
375+
x: []byte(`[
376+
[
377+
{"lon":77.58894681930542,"lat":12.976498523818783},
378+
{"lon":77.58677959442139,"lat":12.974533005048169},
379+
{"lon":77.58894681930542,"lat":12.976498523818783}
380+
]
381+
]`),
382+
typ: PolygonType,
383+
expectOK: false,
384+
},
385+
{ // Invalid construct causes panic (within extract3DCoordinates), fix MB-65807
386+
x: []byte(`{
387+
"coordinates": [
388+
[77.58894681930542,12.976498523818783],
389+
[77.58677959442139,12.974533005048169],
390+
[77.58894681930542,12.976498523818783]
391+
]
392+
}`),
393+
typ: PolygonType,
394+
expectOK: false,
395+
},
396+
{
397+
x: []byte(`[
398+
[
399+
[
400+
[-0.163421630859375,51.531600743186644],
401+
[-0.15277862548828125,51.52455221546295],
402+
[-0.15895843505859375,51.53693981046689],
403+
[-0.163421630859375,51.531600743186644]
404+
]
405+
],
406+
[
407+
[
408+
[-0.1902008056640625,51.5091698216777],
409+
[-0.1599884033203125,51.51322956905176],
410+
[-0.1902008056640625,51.5091698216777]
411+
]
412+
]
413+
]`),
414+
typ: MultiPolygonType,
415+
expectOK: true,
416+
},
417+
{ // Invalid construct causes panic (within extract3DCoordinates), fix MB-65807
418+
x: []byte(`[
419+
{
420+
"coordinates": [
421+
[-0.163421630859375,51.531600743186644],
422+
[-0.15277862548828125,51.52455221546295],
423+
[-0.15895843505859375,51.53693981046689],
424+
[-0.163421630859375,51.531600743186644]
425+
]
426+
},
427+
{
428+
"coordinates": [
429+
[-0.1902008056640625,51.5091698216777],
430+
[-0.1599884033203125,51.51322956905176],
431+
[-0.1902008056640625,51.5091698216777]
432+
]
433+
}
434+
]`),
435+
typ: MultiPolygonType,
436+
expectOK: false,
437+
},
438+
}
439+
440+
for i := range tests {
441+
var x interface{}
442+
if err := json.Unmarshal(tests[i].x, &x); err != nil {
443+
t.Fatalf("[%d] JSON err: %v", i+1, err)
444+
}
445+
446+
_, typ, ok := ExtractGeoShapeCoordinates(x, tests[i].typ)
447+
if ok != tests[i].expectOK {
448+
t.Errorf("[%d] expected ok %t, got %t", i+1, tests[i].expectOK, ok)
449+
}
450+
451+
if ok && typ != tests[i].typ {
452+
t.Errorf("[%d] expected type %s, got %s", i+1, tests[i].typ, typ)
453+
}
454+
}
455+
}

0 commit comments

Comments
 (0)