Skip to content

Commit

Permalink
fix(bigquery): avoid stack overflow on query param with recursive typ…
Browse files Browse the repository at this point in the history
…es (#6890)

Resolves #6884
  • Loading branch information
alvarowolfx committed Oct 24, 2022
1 parent afbecb6 commit 854ccfc
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
7 changes: 7 additions & 0 deletions bigquery/params.go
Expand Up @@ -21,6 +21,7 @@ import (
"math/big"
"reflect"
"regexp"
"strings"
"time"

"cloud.google.com/go/civil"
Expand Down Expand Up @@ -380,6 +381,12 @@ func paramType(t reflect.Type, v reflect.Value) (*bq.QueryParameterType, error)
return nil, err
}
for _, f := range fields {
prefixes := []string{"*", "[]"} // check pointer and arrays
for _, prefix := range prefixes {
if strings.TrimPrefix(t.String(), prefix) == strings.TrimPrefix(f.Type.String(), prefix) {
return nil, fmt.Errorf("bigquery: Go type %s cannot be represented as a parameter due to an attribute cycle/recursion detected", t)
}
}
pt, err := paramType(f.Type, v)
if err != nil {
return nil, err
Expand Down
40 changes: 38 additions & 2 deletions bigquery/params_test.go
Expand Up @@ -282,10 +282,46 @@ func TestParamType(t *testing.T) {
}
}
}

func TestParamTypeErrors(t *testing.T) {
for _, val := range []interface{}{
nil, uint(0), new([]int), make(chan int),
nil, uint(0), new([]int), make(chan int), map[string]interface{}{},
} {
_, err := paramType(reflect.TypeOf(val), reflect.ValueOf(val))
if err == nil {
t.Errorf("%v (%T): got nil, want error", val, val)
}
}

type recArr struct {
RecArr []recArr
}
type recMap struct {
RecMap map[string]recMap
}
queryParam := QueryParameterValue{
StructValue: map[string]QueryParameterValue{
"nested": {
Type: StandardSQLDataType{
TypeKind: "STRING",
},
Value: "TEST",
},
},
}
standardSQL := StandardSQLDataType{
ArrayElementType: &StandardSQLDataType{
TypeKind: "NUMERIC",
},
}
recursiveArr := recArr{
RecArr: []recArr{},
}
recursiveMap := recMap{
RecMap: map[string]recMap{},
}
// Recursive structs
for _, val := range []interface{}{
queryParam, standardSQL, recursiveArr, recursiveMap,
} {
_, err := paramType(reflect.TypeOf(val), reflect.ValueOf(val))
if err == nil {
Expand Down

0 comments on commit 854ccfc

Please sign in to comment.