/src/freeradius-server/src/fuzzer/fuzzer_json.c
Line | Count | Source |
1 | | /* |
2 | | * This program is free software; you can redistribute it and/or modify |
3 | | * it under the terms of the GNU General Public License as published by |
4 | | * the Free Software Foundation; either version 2 of the License, or |
5 | | * (at your option) any later version. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
15 | | */ |
16 | | |
17 | | /** |
18 | | * $Id: 3281402f3d8d7b4ed480616e9425d0f6bf064eb7 $ |
19 | | * |
20 | | * @file src/bin/fuzzer_json.c |
21 | | * @brief Functions to fuzz json |
22 | | * */ |
23 | | RCSID("$Id: 3281402f3d8d7b4ed480616e9425d0f6bf064eb7 $") |
24 | | |
25 | | #include <freeradius-devel/build.h> |
26 | | #include <freeradius-devel/util/talloc.h> |
27 | | |
28 | | DIAG_OFF(documentation) |
29 | | DIAG_OFF(deprecated) |
30 | | |
31 | | #include <stdint.h> |
32 | | #include <stddef.h> |
33 | | #include <stdlib.h> |
34 | | #include <string.h> |
35 | | #include <stdbool.h> |
36 | | #include <sys/types.h> |
37 | | #include <json-c/json.h> |
38 | | |
39 | | /* Forward declarations for FreeRADIUS types to avoid header complexity */ |
40 | | typedef struct fr_jpath_node_s fr_jpath_node_t; |
41 | | |
42 | | /* External declarations for functions */ |
43 | | extern ssize_t fr_jpath_parse(void *ctx, fr_jpath_node_t **head, |
44 | | char const *in, size_t inlen); |
45 | | |
46 | | int LLVMFuzzerInitialize(int *argc, char ***argv); |
47 | | int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len); |
48 | | |
49 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
50 | 3.14k | { |
51 | 3.14k | void *ctx = NULL; |
52 | 3.14k | size_t split_point; |
53 | | |
54 | | /* Need at least 2 bytes */ |
55 | 3.14k | if (size < 2) { |
56 | 1 | return 0; |
57 | 1 | } |
58 | | |
59 | | /* Limit input size to prevent timeouts */ |
60 | 3.14k | if (size > 8192) { |
61 | 18 | return 0; |
62 | 18 | } |
63 | | |
64 | | /* Initialize talloc context */ |
65 | 3.12k | ctx = talloc_init("fuzzer_json"); |
66 | 3.12k | if (!ctx) { |
67 | 0 | return 0; |
68 | 0 | } |
69 | | |
70 | | /* |
71 | | * Use first byte to determine split between JSON and jpath |
72 | | */ |
73 | 3.12k | split_point = (data[0] * size) / 256; |
74 | 3.12k | if (split_point >= size - 1) { |
75 | 36 | split_point = size / 2; |
76 | 36 | } |
77 | | |
78 | | /* |
79 | | * JSON string to parse with json-c |
80 | | */ |
81 | 3.12k | if (split_point > 1) { |
82 | 2.44k | char *str = NULL; |
83 | 2.44k | json_object *json_obj = NULL; |
84 | | |
85 | 2.44k | str = talloc_strndup(ctx, (const char *)(data + 1), split_point - 1); |
86 | 2.44k | if (str) { |
87 | 2.44k | json_obj = json_tokener_parse(str); |
88 | 2.44k | if (json_obj) { |
89 | 430 | json_object_put(json_obj); |
90 | 430 | json_obj = NULL; |
91 | 430 | } |
92 | 2.44k | } |
93 | 2.44k | } |
94 | | |
95 | | /* |
96 | | * jpath expression string to parse with FreeRADIUS |
97 | | */ |
98 | 3.12k | if (split_point < size - 1) { |
99 | 3.12k | size_t len = size - split_point - 1; |
100 | 3.12k | char *str = NULL; |
101 | 3.12k | fr_jpath_node_t *jpath_head = NULL; |
102 | | |
103 | 3.12k | if (len > 0) { |
104 | 3.12k | str = talloc_strndup(ctx, |
105 | 3.12k | (const char *)(data + split_point + 1), |
106 | 3.12k | len); |
107 | 3.12k | } |
108 | | |
109 | 3.12k | if (str) { |
110 | | /* |
111 | | * the strdup functions stop at the first 0. So we need to pass the actual |
112 | | * length of "str", and not the input "len". |
113 | | * |
114 | | * Since the json code also stops at the first NUL, character, there's no benefit |
115 | | * to passing any more than that. |
116 | | */ |
117 | 3.12k | (void) fr_jpath_parse(ctx, &jpath_head, str, talloc_strlen(str)); |
118 | 3.12k | } |
119 | 3.12k | } |
120 | | |
121 | | talloc_free(ctx); |
122 | 3.12k | return 0; |
123 | 3.12k | } |