Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,16 @@ func FuzzDetect(f *testing.F) {
}
assertResultInvariants(t, first, false, len(data))
binary, _ := binaryFormat(data)
expectJSON := binary == "" && json.Valid(data) && utf8.Valid(data)
container := hasJSONContainerPrefix(data)
expectJSON := binary == "" && container && json.Valid(data) && utf8.Valid(data)
if got := first.Format == FormatJSON; got != expectJSON {
t.Fatalf("Detect JSON match = %v, want %v for %x", got, expectJSON, data)
}

prefix := DetectPrefix(data)
if len(data) > 0 {
expectedPrefix := first
if parseJSON(data) == jsonIncomplete {
if container && parseJSON(data) == jsonIncomplete {
expectedPrefix.Format = FormatJSON
expectedPrefix.MIME = mimeJSON
}
Expand Down
11 changes: 11 additions & 0 deletions json.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,21 @@ type jsonParser struct {
}

func isJSON(data []byte, prefix bool) bool {
if !hasJSONContainerPrefix(data) {
return false
}
result := parseJSON(data)
return result == jsonComplete || prefix && result == jsonIncomplete
}

func hasJSONContainerPrefix(data []byte) bool {
i := 0
for i < len(data) && isJSONWhitespace(data[i]) {
i++
}
return i < len(data) && (data[i] == '{' || data[i] == '[')
}

func parseJSON(data []byte) jsonParseResult {
parser := jsonParser{data: data}
parser.skipWhitespace()
Expand Down
34 changes: 19 additions & 15 deletions json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ func TestJSONDetection(t *testing.T) {
}{
{name: "object", input: `{"schemaVersion": 2}`},
{name: "array", input: `[1, "two", false, null]`},
{name: "string", input: `"hello"`},
{name: "number", input: `-12.5e+2`},
{name: "true", input: `true`},
{name: "false", input: `false`},
{name: "null", input: `null`},
{name: "surrounding whitespace", input: " \t\r\n{\"key\": \"value\"}\n"},
{name: "Unicode", input: `{"message":"héllo, 世界","escaped":"\uD834\uDD1E"}`},
{name: "escaped characters", input: `["\b\f\n\r\t\/\\\""]`},
Expand All @@ -44,6 +39,12 @@ func TestInvalidJSONRetainsExistingClassification(t *testing.T) {
name string
input string
}{
{name: "bare string", input: `"hello"`},
{name: "bare number", input: `-12.5e+2`},
{name: "bare integer", input: `12345`},
{name: "bare true", input: `true`},
{name: "bare false", input: `false`},
{name: "bare null", input: `null`},
{name: "mismatched delimiters", input: `{]`},
{name: "whitespace only", input: " \t\r\n"},
{name: "missing value", input: `{"key":}`},
Expand Down Expand Up @@ -144,16 +145,16 @@ func TestJSONPrefixDetection(t *testing.T) {
{name: "truncated object value", input: `{"key":`},
{name: "truncated array", input: `[`},
{name: "truncated array value", input: `[1,`},
{name: "truncated string", input: `"value`},
{name: "truncated escape", input: `"value\`},
{name: "truncated Unicode escape", input: `"value\u12`},
{name: "truncated negative number", input: `-`},
{name: "truncated fraction", input: `1.`},
{name: "truncated exponent", input: `1e`},
{name: "truncated signed exponent", input: `1e+`},
{name: "truncated true", input: `tru`},
{name: "truncated false", input: `fals`},
{name: "truncated null", input: `nul`},
{name: "truncated array string", input: `["value`},
{name: "truncated array escape", input: `["value\`},
{name: "truncated array Unicode escape", input: `["value\u12`},
{name: "truncated array number", input: `[-`},
{name: "truncated array fraction", input: `[1.`},
{name: "truncated array exponent", input: `[1e`},
{name: "truncated array signed exponent", input: `[1e+`},
{name: "truncated array true", input: `[tru`},
{name: "truncated array false", input: `[fals`},
{name: "truncated array null", input: `[nul`},
{name: "leading whitespace", input: " \n{"},
}

Expand All @@ -179,6 +180,9 @@ func TestInvalidJSONPrefixRetainsExistingClassification(t *testing.T) {
input string
}{
{name: "plain text", input: `package`},
{name: "bare number", input: `123`},
{name: "bare string", input: `"value`},
{name: "bare literal", input: `tru`},
{name: "whitespace only", input: " \t\r\n"},
{name: "mismatched delimiters", input: `{]`},
{name: "trailing comma", input: `[1,]`},
Expand Down