types/time: filter string that cannot be a unix timestamp (#1715)

* types/time: strict usage of time type for usage with unix timestamps

* Update types/time_test.go

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>

* @cranktakular: nits

* glorious: nits

---------

Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io>
Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
This commit is contained in:
Ryan O'Hara-Reid
2024-12-04 10:00:09 +11:00
committed by GitHub
parent 291b7b58ea
commit b98e82db54
2 changed files with 22 additions and 5 deletions

View File

@@ -28,7 +28,21 @@ func (t *Time) UnmarshalJSON(data []byte) error {
s = s[1 : len(s)-1]
}
if target := strings.Index(s, "."); target != -1 {
badSyntax := false
target := strings.IndexFunc(s, func(r rune) bool {
if r == '.' {
return true
}
// types.Time may only parse numbers. The below check ensures an error is thrown. time.Time should be used to
// parse RFC3339 strings instead.
badSyntax = r < '0' || r > '9'
return badSyntax
})
if target != -1 {
if badSyntax {
return fmt.Errorf("%w for `%v`", strconv.ErrSyntax, string(data))
}
s = s[:target] + s[target+1:]
}

View File

@@ -56,17 +56,20 @@ func TestUnmarshalJSON(t *testing.T) {
require.ErrorIs(t, json.Unmarshal([]byte(`"blurp"`), &testTime), strconv.ErrSyntax)
require.Error(t, json.Unmarshal([]byte(`"123456"`), &testTime))
// Captures bad syntax when type should be time.Time (RFC3339)
require.ErrorIs(t, json.Unmarshal([]byte(`"2025-03-28T08:00:00Z"`), &testTime), strconv.ErrSyntax)
// parse int failure
require.ErrorIs(t, json.Unmarshal([]byte(`"1606292218213.45.8"`), &testTime), strconv.ErrSyntax)
}
// 5046307 216.0 ns/op 168 B/op 2 allocs/op (current)
// 5030734 240.1 ns/op 168 B/op 2 allocs/op (current)
// 2716176 441.9 ns/op 352 B/op 6 allocs/op (previous)
func BenchmarkUnmarshalJSON(b *testing.B) {
var testTime Time
for i := 0; i < b.N; i++ {
err := json.Unmarshal([]byte(`"1691122380942.173000"`), &testTime)
if err != nil {
b.Fatal(err)
}
require.NoError(b, err)
}
}