Freeze catalog signature vectors (T-614)
This commit is contained in:
@@ -10,12 +10,15 @@ import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var integerJSONNumber = regexp.MustCompile(`^-?(0|[1-9][0-9]*)$`)
|
||||
var integerJSONNumber = regexp.MustCompile(`^(0|[1-9][0-9]*|-[1-9][0-9]*)$`)
|
||||
|
||||
func parseRestrictedJSON(data []byte) (any, error) {
|
||||
if !utf8.Valid(data) {
|
||||
return nil, fmt.Errorf("%w: input is not valid UTF-8", ErrInvalidDocument)
|
||||
}
|
||||
if err := validateJSONStringSurrogates(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
decoder := json.NewDecoder(bytes.NewReader(data))
|
||||
decoder.UseNumber()
|
||||
|
||||
@@ -33,6 +36,78 @@ func parseRestrictedJSON(data []byte) (any, error) {
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func validateJSONStringSurrogates(data []byte) error {
|
||||
for index := 0; index < len(data); index++ {
|
||||
if data[index] != '"' {
|
||||
continue
|
||||
}
|
||||
next, err := scanJSONStringSurrogates(data, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
index = next - 1
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scanJSONStringSurrogates(data []byte, start int) (int, error) {
|
||||
for index := start + 1; index < len(data); index++ {
|
||||
switch data[index] {
|
||||
case '"':
|
||||
return index + 1, nil
|
||||
case '\\':
|
||||
if index+1 >= len(data) {
|
||||
return 0, fmt.Errorf("%w: incomplete string escape", ErrInvalidDocument)
|
||||
}
|
||||
if data[index+1] != 'u' {
|
||||
index++
|
||||
continue
|
||||
}
|
||||
codeUnit, ok := decodeJSONHexCodeUnit(data, index+2)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("%w: invalid unicode escape", ErrInvalidDocument)
|
||||
}
|
||||
switch {
|
||||
case codeUnit >= 0xd800 && codeUnit <= 0xdbff:
|
||||
if index+7 >= len(data) || data[index+6] != '\\' || data[index+7] != 'u' {
|
||||
return 0, fmt.Errorf("%w: high surrogate is not paired", ErrInvalidDocument)
|
||||
}
|
||||
lowSurrogate, ok := decodeJSONHexCodeUnit(data, index+8)
|
||||
if !ok || lowSurrogate < 0xdc00 || lowSurrogate > 0xdfff {
|
||||
return 0, fmt.Errorf("%w: high surrogate is not followed by a low surrogate", ErrInvalidDocument)
|
||||
}
|
||||
index += 11
|
||||
case codeUnit >= 0xdc00 && codeUnit <= 0xdfff:
|
||||
return 0, fmt.Errorf("%w: low surrogate has no high surrogate", ErrInvalidDocument)
|
||||
default:
|
||||
index += 5
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("%w: unterminated string", ErrInvalidDocument)
|
||||
}
|
||||
|
||||
func decodeJSONHexCodeUnit(data []byte, start int) (uint16, bool) {
|
||||
if start+4 > len(data) {
|
||||
return 0, false
|
||||
}
|
||||
var value uint16
|
||||
for _, digit := range data[start : start+4] {
|
||||
value <<= 4
|
||||
switch {
|
||||
case digit >= '0' && digit <= '9':
|
||||
value |= uint16(digit - '0')
|
||||
case digit >= 'a' && digit <= 'f':
|
||||
value |= uint16(digit-'a') + 10
|
||||
case digit >= 'A' && digit <= 'F':
|
||||
value |= uint16(digit-'A') + 10
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
return value, true
|
||||
}
|
||||
|
||||
func decodeJSONValue(decoder *json.Decoder) (any, error) {
|
||||
token, err := decoder.Token()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user