Skip to content

Commit 62357a7

Browse files
committed
Fix crash in JSON parser
1 parent 12eaad9 commit 62357a7

File tree

8 files changed

+105
-0
lines changed

8 files changed

+105
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*.o
22
/*.a
3+
/fuzz
34
/*.ok
45
/*.elf
56
/*.dbg

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ clean:
77

88
json.o: json.cpp json.h
99

10+
fuzz.o: fuzz.cpp json.h
11+
fuzz: fuzz.o json.o double-conversion.a
12+
1013
json_test.o: json_test.cpp json.h
1114
json_test: json_test.o json.o double-conversion.a
1215

fuzz.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// -*- mode:c++;indent-tabs-mode:nil;c-basic-offset:4;coding:utf-8 -*-
2+
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
3+
//
4+
// Copyright 2024 Mozilla Foundation
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
#include "json.h"
19+
20+
#include <cstdio>
21+
#include <string>
22+
23+
int
24+
main(int argc, char* argv[])
25+
{
26+
int c;
27+
std::string s;
28+
while ((c = fgetc(stdin)) != EOF)
29+
s += c;
30+
std::pair<Json::Status, Json> result = Json::parse(s);
31+
if (result.first != Json::success) {
32+
puts(Json::StatusToString(result.first));
33+
return 1;
34+
}
35+
puts(result.second.toStringPretty().c_str());
36+
}

fuzzies/t1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[1, 2, 3]

fuzzies/t2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"a": "b"}

fuzzies/t3

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[
2+
null,
3+
1,
4+
3.14,
5+
{"a": "b"}
6+
]

json.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,8 @@ Json::parse(Json& json, const char*& p, const char* e, int context, int depth)
951951
return success;
952952
if (status != success)
953953
return status;
954+
if (!key.isString())
955+
return object_key_must_be_string;
954956
status = parse(value, p, e, COLON, depth - 1);
955957
if (status == absent_value)
956958
return object_missing_value;

json_test.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,13 +406,68 @@ json_test_suite()
406406
}
407407
}
408408

409+
void
410+
afl_regression()
411+
{
412+
Json::parse("[{\"\":1,3:14,]\n");
413+
Json::parse("[\n"
414+
"\n"
415+
"3E14,\n"
416+
"{\"!\":4,733:4,[\n"
417+
"\n"
418+
"3EL%,3E14,\n"
419+
"{][1][1,,]");
420+
Json::parse("[\n"
421+
"null,\n"
422+
"1,\n"
423+
"3.14,\n"
424+
"{\"a\": \"b\",\n"
425+
"3:14,ull}\n"
426+
"]");
427+
Json::parse("[\n"
428+
"\n"
429+
"3E14,\n"
430+
"{\"a!!!!!!!!!!!!!!!!!!\":4, \n"
431+
"\n"
432+
"3:1,,\n"
433+
"3[\n"
434+
"\n"
435+
"]");
436+
Json::parse("[\n"
437+
"\n"
438+
"3E14,\n"
439+
"{\"a!!:!!!!!!!!!!!!!!!\":4, \n"
440+
"\n"
441+
"3E1:4, \n"
442+
"\n"
443+
"3E1,,\n"
444+
",,\n"
445+
"3[\n"
446+
"\n"
447+
"]");
448+
Json::parse("[\n"
449+
"\n"
450+
"3E14,\n"
451+
"{\"!\":4,733:4,[\n"
452+
"\n"
453+
"3E1%,][1,,]");
454+
Json::parse("[\n"
455+
"\n"
456+
"3E14,\n"
457+
"{\"!\":4,733:4,[\n"
458+
"\n"
459+
"3EL%,3E14,\n"
460+
"{][1][1,,]");
461+
}
462+
409463
int
410464
main()
411465
{
412466
object_test();
413467
deep_test();
414468
parse_test();
415469
round_trip_test();
470+
afl_regression();
416471

417472
BENCH(2000, 1, object_test());
418473
BENCH(2000, 1, deep_test());

0 commit comments

Comments
 (0)