forked from TrueCloudLab/neoneo-go
stackitem: allow to unJSONize big numbers (>int64), fix #2477
100000000000000000000 overflows int64 and NeoGo returns some garbage to contracts instead of a proper number.
This commit is contained in:
parent
3d1a81df1f
commit
621db8c832
1 changed files with 19 additions and 5 deletions
|
@ -7,9 +7,9 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
gio "io"
|
gio "io"
|
||||||
"math"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// decoder is a wrapper around json.Decoder helping to mimic C# json decoder behaviour.
|
// decoder is a wrapper around json.Decoder helping to mimic C# json decoder behaviour.
|
||||||
|
@ -164,6 +164,7 @@ func FromJSON(data []byte, maxCount int) (Item, error) {
|
||||||
Decoder: *json.NewDecoder(bytes.NewReader(data)),
|
Decoder: *json.NewDecoder(bytes.NewReader(data)),
|
||||||
count: maxCount,
|
count: maxCount,
|
||||||
}
|
}
|
||||||
|
d.UseNumber()
|
||||||
if item, err := d.decode(); err != nil {
|
if item, err := d.decode(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if _, err := d.Token(); err != gio.EOF {
|
} else if _, err := d.Token(); err != gio.EOF {
|
||||||
|
@ -208,11 +209,24 @@ func (d *decoder) decode() (Item, error) {
|
||||||
}
|
}
|
||||||
case string:
|
case string:
|
||||||
return NewByteArray([]byte(t)), nil
|
return NewByteArray([]byte(t)), nil
|
||||||
case float64:
|
case json.Number:
|
||||||
if math.Floor(t) != t {
|
ts := t.String()
|
||||||
return nil, fmt.Errorf("%w (real value for int)", ErrInvalidValue)
|
dot := strings.IndexByte(ts, '.')
|
||||||
|
if dot != -1 {
|
||||||
|
// As a special case numbers like 123.000 are allowed (SetString rejects them).
|
||||||
|
// And yes, that's the way C# code works also.
|
||||||
|
for _, r := range ts[dot+1:] {
|
||||||
|
if r != '0' {
|
||||||
|
return nil, fmt.Errorf("%w (real value for int)", ErrInvalidValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ts = ts[:dot]
|
||||||
}
|
}
|
||||||
return NewBigInteger(big.NewInt(int64(t))), nil
|
num, ok := new(big.Int).SetString(ts, 10)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("%w (integer)", ErrInvalidValue)
|
||||||
|
}
|
||||||
|
return NewBigInteger(num), nil
|
||||||
case bool:
|
case bool:
|
||||||
return NewBool(t), nil
|
return NewBool(t), nil
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue