Freeze catalog signature vectors (T-614)

This commit is contained in:
ila
2026-07-18 16:46:17 +08:00
parent 9e5f3f4840
commit 0c1b7662c6
11 changed files with 370 additions and 32 deletions
+76 -1
View File
@@ -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 {