@@ -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