Skip to content

Commit

Permalink
ngerous serialization in slices.Strings, broken behavior fixes #342 (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
markbates authored and stanislas-m committed Feb 15, 2019
1 parent ea82301 commit 87b1998
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 29 deletions.
18 changes: 9 additions & 9 deletions packrd/packed-packr.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 27 additions & 20 deletions slices/string.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package slices

import (
"bytes"
"database/sql/driver"
"encoding/csv"
"encoding/json"
"fmt"
"io"
"strings"

"github.com/pkg/errors"
"github.com/lib/pq"
)

// For reading in arrays from postgres

// String is a slice of strings.
type String []string
type String pq.StringArray

// Interface implements the nulls.nullable interface.
func (s String) Interface() interface{} {
Expand All @@ -22,24 +24,23 @@ func (s String) Interface() interface{} {
// Scan implements the sql.Scanner interface.
// It allows to read the string slice from the database value.
func (s *String) Scan(src interface{}) error {
b, ok := src.([]byte)
if !ok {
return errors.New("Scan source was not []byte")
}
*s = strToString(string(b))
return nil
ss := pq.StringArray(*s)
err := ss.Scan(src)
*s = String(ss)
return err
}

// Value implements the driver.Valuer interface.
// It allows to convert the string slice to a driver.value.
func (s String) Value() (driver.Value, error) {
return fmt.Sprintf("{%s}", strings.Join(s, ",")), nil
ss := pq.StringArray(s)
return ss.Value()
}

// UnmarshalJSON will unmarshall JSON value into
// the string slice representation of this value.
func (s *String) UnmarshalJSON(data []byte) error {
var ss []string
var ss pq.StringArray
if err := json.Unmarshal(data, &ss); err != nil {
return err
}
Expand All @@ -50,11 +51,22 @@ func (s *String) UnmarshalJSON(data []byte) error {
// UnmarshalText will unmarshall text value into
// the string slice representation of this value.
func (s *String) UnmarshalText(text []byte) error {
var ss []string
for _, x := range strings.Split(string(text), ",") {
ss = append(ss, strings.TrimSpace(x))
r := csv.NewReader(bytes.NewReader(text))

var words []string
for {
record, err := r.Read()
if err == io.EOF {
break
}
if err != nil {
return err
}

words = append(words, record...)
}
*s = ss

*s = String(words)
return nil
}

Expand All @@ -67,8 +79,3 @@ func (s String) TagValue() string {
func (s String) Format(sep string) string {
return strings.Join([]string(s), sep)
}

func strToString(s string) []string {
r := strings.Trim(s, "{}")
return strings.Split(r, ",")
}
29 changes: 29 additions & 0 deletions slices/string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,35 @@ import (
"github.com/stretchr/testify/require"
)

func Test_String_Scan(t *testing.T) {
r := require.New(t)
in := `{"This has a comma,","This has a double quote\"","Also a single'"}`
s := &String{}
r.NoError(s.Scan(in))
ss := []string(*s)
r.Len(ss, 3)
r.Equal([]string{"This has a comma,", "This has a double quote\"", "Also a single'"}, ss)
}

func Test_String_Value(t *testing.T) {
r := require.New(t)
s := String{"This has a comma,", "This has a double quote\"", "Also a single'"}
v, err := s.Value()
r.NoError(err)
r.Equal(`{"This has a comma,","This has a double quote\"","Also a single'"}`, v)
}

func Test_String_UnmarshalText(t *testing.T) {
r := require.New(t)
in := "foo,bar,\"baz,bax\""
s := &String{}
r.NoError(s.UnmarshalText([]byte(in)))

ss := []string(*s)
r.Len(ss, 3)
r.Equal([]string{"foo", "bar", "baz,bax"}, ss)
}

func Test_String_JSON_Unmarshal(t *testing.T) {
r := require.New(t)

Expand Down

0 comments on commit 87b1998

Please sign in to comment.