Skip to content

Commit 36fb447

Browse files
committed
weak
1 parent e5b404f commit 36fb447

1 file changed

Lines changed: 85 additions & 14 deletions

File tree

‎core/pkg/model/serde.go‎

Lines changed: 85 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"encoding/json/v2"
1212
"errors"
1313
"fmt"
14+
"math"
1415
"reflect"
1516
"strconv"
1617
"strings"
@@ -145,15 +146,33 @@ func weaklyInteger[I integer]() func(d *jsontext.Decoder, n *I) error {
145146
signed := t.Kind() <= reflect.Int64
146147
bitSize := t.Bits()
147148

149+
var minVal, maxVal int64
150+
var maxUintVal uint64
151+
if signed {
152+
if bitSize == 64 {
153+
minVal = math.MinInt64
154+
maxVal = math.MaxInt64
155+
} else {
156+
minVal = int64(-1) << (bitSize - 1)
157+
maxVal = int64(1<<(bitSize-1) - 1)
158+
}
159+
} else {
160+
if bitSize == 64 {
161+
maxUintVal = math.MaxUint64
162+
} else {
163+
maxUintVal = uint64(1<<bitSize - 1)
164+
}
165+
}
166+
148167
return func(d *jsontext.Decoder, n *I) error {
149168
switch k := d.PeekKind(); k {
150169
case jsontext.KindNumber:
151170
if tok, err := d.ReadToken(); err != nil {
152171
return err
153172
} else if signed {
154-
return convertTok(n, tok, jsontext.Token.Int)
173+
return convertSignedTok(n, tok, minVal, maxVal)
155174
} else {
156-
return convertTok(n, tok, jsontext.Token.Uint)
175+
return convertUnsignedTok(n, tok, maxUintVal)
157176
}
158177

159178
case jsontext.KindString:
@@ -168,9 +187,9 @@ func weaklyInteger[I integer]() func(d *jsontext.Decoder, n *I) error {
168187
*n = 0
169188
return nil
170189
} else if signed {
171-
return parseString(n, s, bitSize, strconv.ParseInt)
190+
return parseSignedString(n, s, bitSize, minVal, maxVal)
172191
} else {
173-
return parseString(n, s, bitSize, strconv.ParseUint)
192+
return parseUnsignedString(n, s, bitSize, maxUintVal)
174193
}
175194
case jsontext.KindNull:
176195
if _, err := d.ReadToken(); err != nil {
@@ -232,24 +251,76 @@ func weaklyFloat[F float]() func(d *jsontext.Decoder, f *F) error {
232251
}
233252
}
234253

235-
func convertTok[I, J integer](n *I, tok jsontext.Token, fn func(jsontext.Token) (J, error)) error {
236-
if v, err := fn(tok); err == nil {
254+
func convertSignedTok[I integer](n *I, tok jsontext.Token, minVal, maxVal int64) error {
255+
if v, err := tok.Int(); err == nil {
256+
if v < minVal || v > maxVal {
257+
return fmt.Errorf("integer %d out of range", v)
258+
}
237259
*n = I(v)
238-
} else if f, err := tok.Float(); err == nil {
239-
*n = I(f)
240-
} else {
260+
return nil
261+
}
262+
f, err := tok.Float()
263+
if err != nil {
241264
return err
242265
}
266+
if math.IsNaN(f) || math.IsInf(f, 0) || f < float64(minVal) || f > float64(maxVal) {
267+
return fmt.Errorf("number %g out of range", f)
268+
}
269+
*n = I(int64(f))
243270
return nil
244271
}
245272

246-
func parseString[I, J integer](n *I, s string, bitSize int, fn func(string, int, int) (J, error)) error {
247-
if v, err := fn(s, 0, bitSize); err == nil {
273+
func convertUnsignedTok[I integer](n *I, tok jsontext.Token, maxVal uint64) error {
274+
if v, err := tok.Uint(); err == nil {
275+
if v > maxVal {
276+
return fmt.Errorf("unsigned integer %d out of range", v)
277+
}
248278
*n = I(v)
249-
} else if f, err := strconv.ParseFloat(s, 64); err == nil {
250-
*n = I(f)
251-
} else {
279+
return nil
280+
}
281+
f, err := tok.Float()
282+
if err != nil {
252283
return err
253284
}
285+
if math.IsNaN(f) || math.IsInf(f, 0) || f < 0 || f > float64(maxVal) {
286+
return fmt.Errorf("number %g out of range", f)
287+
}
288+
*n = I(uint64(f))
289+
return nil
290+
}
291+
292+
func parseSignedString[I integer](n *I, s string, bitSize int, minVal, maxVal int64) error {
293+
if v, err := strconv.ParseInt(s, 0, bitSize); err == nil {
294+
*n = I(v)
295+
return nil
296+
} else if errors.Is(err, strconv.ErrRange) {
297+
return err
298+
}
299+
f, err := strconv.ParseFloat(s, 64)
300+
if err != nil {
301+
return err
302+
}
303+
if math.IsNaN(f) || math.IsInf(f, 0) || f < float64(minVal) || f > float64(maxVal) {
304+
return fmt.Errorf("number %g out of range", f)
305+
}
306+
*n = I(int64(f))
307+
return nil
308+
}
309+
310+
func parseUnsignedString[I integer](n *I, s string, bitSize int, maxVal uint64) error {
311+
if v, err := strconv.ParseUint(s, 0, bitSize); err == nil {
312+
*n = I(v)
313+
return nil
314+
} else if errors.Is(err, strconv.ErrRange) {
315+
return err
316+
}
317+
f, err := strconv.ParseFloat(s, 64)
318+
if err != nil {
319+
return err
320+
}
321+
if math.IsNaN(f) || math.IsInf(f, 0) || f < 0 || f > float64(maxVal) {
322+
return fmt.Errorf("number %g out of range", f)
323+
}
324+
*n = I(uint64(f))
254325
return nil
255326
}

0 commit comments

Comments
 (0)