summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--decode.go15
-rw-r--r--errors.go15
-rw-r--r--parse.go15
3 files changed, 31 insertions, 14 deletions
diff --git a/decode.go b/decode.go
index e4fdd77..b1cc90f 100644
--- a/decode.go
+++ b/decode.go
@@ -45,6 +45,8 @@ type Decoder struct {
stack []decodeStackItem
}
+const maxNestingDepth = 10000
+
func NewDecoder(r io.Reader) *Decoder {
rr, ok := r.(io.RuneReader)
if !ok {
@@ -54,6 +56,9 @@ func NewDecoder(r io.Reader) *Decoder {
io: &noWSRuneTypeScanner{
inner: &runeTypeScannerImpl{
inner: rr,
+ parser: Parser{
+ MaxDepth: maxNestingDepth,
+ },
},
},
}
@@ -70,18 +75,8 @@ func (dec *Decoder) More() bool {
return e == nil && t != RuneTypeEOF
}
-const maxNestingDepth = 10000
-
func (dec *Decoder) stackPush(par reflect.Type, idx any) {
dec.stack = append(dec.stack, decodeStackItem{par, idx})
- if len(dec.stack) > maxNestingDepth {
- panic(decodeError{
- Field: dec.stackStr(),
- FieldParent: dec.stackParent(),
- FieldName: dec.stackName(),
- Err: ErrDecodeExceededMaxDepth,
- })
- }
}
func (dec *Decoder) stackPop() {
dec.stack = dec.stack[:len(dec.stack)-1]
diff --git a/errors.go b/errors.go
index a5a4080..cee82f7 100644
--- a/errors.go
+++ b/errors.go
@@ -6,10 +6,21 @@ package lowmemjson
import (
"encoding/json"
+ "errors"
"fmt"
"reflect"
"strings"
- "errors"
+)
+
+// parser errors ///////////////////////////////////////////////////////////////////////////////////
+
+type ParseError struct {
+ Err error
+ Offset int64
+}
+
+var (
+ ErrParserExceededMaxDepth = errors.New("exceeded max depth")
)
// low-level decode errors /////////////////////////////////////////////////////////////////////////
@@ -65,8 +76,6 @@ func (e *DecodeTypeError) Error() string {
func (e *DecodeTypeError) Unwrap() error { return e.Err }
-var ErrDecodeExceededMaxDepth = errors.New("exceeded max depth")
-
// high-level decode errors ////////////////////////////////////////////////////////////////////////
// A *DecodeArgumentError is returned from Decode if the argument is
diff --git a/parse.go b/parse.go
index 23df5bc..fb72280 100644
--- a/parse.go
+++ b/parse.go
@@ -204,6 +204,11 @@ func (t RuneType) IsNumber() bool {
}
type Parser struct {
+ // Setting MaxError to a value greater than 0 causes
+ // HandleRune to return ErrParserExceededMaxDepth if
+ // objects/arrays become nested more deeply than this.
+ MaxDepth int
+
initialized bool
err error
@@ -286,7 +291,9 @@ func (par *Parser) stackString() string {
// Reset all Parser state.
func (par *Parser) Reset() {
- *par = Parser{}
+ *par = Parser{
+ MaxDepth: par.MaxDepth,
+ }
}
// HandleEOF feeds EOF to the Parser. The returned RuneType is either
@@ -370,8 +377,14 @@ func (par *Parser) HandleRune(c rune) (RuneType, error) {
case 0x0020, 0x000A, 0x000D, 0x0009:
return RuneTypeSpace, nil
case '{':
+ if par.MaxDepth > 0 && len(par.stack) > par.MaxDepth {
+ return RuneTypeError, ErrParserExceededMaxDepth
+ }
return par.replaceState(RuneTypeObjectBeg), nil
case '[':
+ if par.MaxDepth > 0 && len(par.stack) > par.MaxDepth {
+ return RuneTypeError, ErrParserExceededMaxDepth
+ }
return par.replaceState(RuneTypeArrayBeg), nil
case '"':
return par.replaceState(RuneTypeStringBeg), nil