forked from mirror/jwt
Fixed integer overflow in NumericDate.MarshalJSON (#200)
This commit is contained in:
parent
8fb42696ff
commit
2da0bf7566
18
types.go
18
types.go
|
@ -53,9 +53,23 @@ func (date NumericDate) MarshalJSON() (b []byte, err error) {
|
|||
if TimePrecision < time.Second {
|
||||
prec = int(math.Log10(float64(time.Second) / float64(TimePrecision)))
|
||||
}
|
||||
f := float64(date.Truncate(TimePrecision).UnixNano()) / float64(time.Second)
|
||||
truncatedDate := date.Truncate(TimePrecision)
|
||||
|
||||
return []byte(strconv.FormatFloat(f, 'f', prec, 64)), nil
|
||||
// For very large timestamps, UnixNano would overflow an int64, but this
|
||||
// function requires nanosecond level precision, so we have to use the
|
||||
// following technique to get round the issue:
|
||||
// 1. Take the normal unix timestamp to form the whole number part of the
|
||||
// output,
|
||||
// 2. Take the result of the Nanosecond function, which retuns the offset
|
||||
// within the second of the particular unix time instance, to form the
|
||||
// decimal part of the output
|
||||
// 3. Concatenate them to produce the final result
|
||||
seconds := strconv.FormatInt(truncatedDate.Unix(), 10)
|
||||
nanosecondsOffset := strconv.FormatFloat(float64(truncatedDate.Nanosecond())/float64(time.Second), 'f', prec, 64)
|
||||
|
||||
output := append([]byte(seconds), []byte(nanosecondsOffset)[1:]...)
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON is an implementation of the json.RawMessage interface and deserializses a
|
||||
|
|
|
@ -2,6 +2,7 @@ package jwt_test
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -79,23 +80,38 @@ func TestNumericDate_MarshalJSON(t *testing.T) {
|
|||
}{
|
||||
{time.Unix(5243700879, 0), "5243700879", time.Second},
|
||||
{time.Unix(5243700879, 0), "5243700879.000", time.Millisecond},
|
||||
{time.Unix(5243700879, 0), "5243700879.000001", time.Microsecond},
|
||||
{time.Unix(5243700879, 0), "5243700879.000000954", time.Nanosecond},
|
||||
{time.Unix(5243700879, 0), "5243700879.000000", time.Microsecond},
|
||||
{time.Unix(5243700879, 0), "5243700879.000000000", time.Nanosecond},
|
||||
//
|
||||
{time.Unix(4239425898, 0), "4239425898", time.Second},
|
||||
{time.Unix(4239425898, 0), "4239425898.000", time.Millisecond},
|
||||
{time.Unix(4239425898, 0), "4239425898.000000", time.Microsecond},
|
||||
{time.Unix(4239425898, 0), "4239425898.000000000", time.Nanosecond},
|
||||
//
|
||||
{time.Unix(253402271999, 0), "253402271999", time.Second},
|
||||
{time.Unix(253402271999, 0), "253402271999.000", time.Millisecond},
|
||||
{time.Unix(253402271999, 0), "253402271999.000000", time.Microsecond},
|
||||
{time.Unix(253402271999, 0), "253402271999.000000000", time.Nanosecond},
|
||||
//
|
||||
{time.Unix(0, 1644285000210402000), "1644285000", time.Second},
|
||||
{time.Unix(0, 1644285000210402000), "1644285000.210", time.Millisecond},
|
||||
{time.Unix(0, 1644285000210402000), "1644285000.210402", time.Microsecond},
|
||||
{time.Unix(0, 1644285000210402000), "1644285000.210402012", time.Nanosecond},
|
||||
{time.Unix(0, 1644285000210402000), "1644285000.210402000", time.Nanosecond},
|
||||
//
|
||||
{time.Unix(0, 1644285315063096000), "1644285315", time.Second},
|
||||
{time.Unix(0, 1644285315063096000), "1644285315.063", time.Millisecond},
|
||||
{time.Unix(0, 1644285315063096000), "1644285315.063096", time.Microsecond},
|
||||
{time.Unix(0, 1644285315063096000), "1644285315.063096046", time.Nanosecond},
|
||||
{time.Unix(0, 1644285315063096000), "1644285315.063096000", time.Nanosecond},
|
||||
// Maximum time that a go time.Time can represent
|
||||
{time.Unix(math.MaxInt64, 999999999), "9223372036854775807", time.Second},
|
||||
{time.Unix(math.MaxInt64, 999999999), "9223372036854775807.999", time.Millisecond},
|
||||
{time.Unix(math.MaxInt64, 999999999), "9223372036854775807.999999", time.Microsecond},
|
||||
{time.Unix(math.MaxInt64, 999999999), "9223372036854775807.999999999", time.Nanosecond},
|
||||
// Strange precisions
|
||||
{time.Unix(math.MaxInt64, 999999999), "9223372036854775807", time.Second},
|
||||
{time.Unix(math.MaxInt64, 999999999), "9223372036854775756", time.Minute},
|
||||
{time.Unix(math.MaxInt64, 999999999), "9223372036854774016", time.Hour},
|
||||
{time.Unix(math.MaxInt64, 999999999), "9223372036854745216", 24 * time.Hour},
|
||||
}
|
||||
|
||||
for i, tc := range tt {
|
||||
|
|
Loading…
Reference in New Issue