Imported Upstream version 1.15.1
[platform/upstream/krb5.git] / src / util / support / t_json.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* util/support/t_json.c - JSON test program */
3 /*
4  * Copyright (c) 2010 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * 3. Neither the name of the Institute nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 /*
38  * Copyright (C) 2012 by the Massachusetts Institute of Technology.
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  *
45  * * Redistributions of source code must retain the above copyright
46  *   notice, this list of conditions and the following disclaimer.
47  *
48  * * Redistributions in binary form must reproduce the above copyright
49  *   notice, this list of conditions and the following disclaimer in
50  *   the documentation and/or other materials provided with the
51  *   distribution.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
54  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
55  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
56  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
57  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
58  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
59  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
60  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
62  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
64  * OF THE POSSIBILITY OF SUCH DAMAGE.
65  */
66
67 #include <errno.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71
72 #include <k5-json.h>
73
74 static void
75 err(const char *str)
76 {
77     fprintf(stderr, "%s\n", str);
78     exit(1);
79 }
80
81 static void
82 check(int pred, const char *str)
83 {
84     if (!pred)
85         err(str);
86 }
87
88 static void
89 test_array()
90 {
91     k5_json_string v1;
92     k5_json_number v2;
93     k5_json_null v3;
94     k5_json_array a;
95     k5_json_value v;
96
97     k5_json_array_create(&a);
98     k5_json_string_create("abc", &v1);
99     k5_json_array_add(a, v1);
100     k5_json_number_create(2, &v2);
101     k5_json_array_add(a, v2);
102     k5_json_null_create(&v3);
103     k5_json_array_add(a, v3);
104
105     check(k5_json_array_length(a) == 3, "array length");
106     v = k5_json_array_get(a, 2);
107     check(k5_json_get_tid(v) == K5_JSON_TID_NULL, "array[2] tid");
108     v = k5_json_array_get(a, 1);
109     check(k5_json_get_tid(v) == K5_JSON_TID_NUMBER, "array[1] tid");
110     check(k5_json_number_value(v) == 2, "array[1] value");
111     v = k5_json_array_get(a, 0);
112     check(k5_json_get_tid(v) == K5_JSON_TID_STRING, "array[0] tid");
113     check(strcmp(k5_json_string_utf8(v), "abc") == 0, "array[0] value");
114
115     k5_json_release(v1);
116     k5_json_release(v2);
117     k5_json_release(a);
118
119     k5_json_array_fmt(&a, "vnbiLssB", v3, 1, 9, (long long)-6, "def", NULL,
120                       (void *)"ghij", (size_t)4);
121     v = k5_json_array_get(a, 0);
122     check(k5_json_get_tid(v) == K5_JSON_TID_NULL, "fmt array[0] tid");
123     v = k5_json_array_get(a, 1);
124     check(k5_json_get_tid(v) == K5_JSON_TID_NULL, "fmt array[1] tid");
125     v = k5_json_array_get(a, 2);
126     check(k5_json_get_tid(v) == K5_JSON_TID_BOOL, "fmt array[2] tid");
127     check(k5_json_bool_value(v), "fmt array[2] value");
128     v = k5_json_array_get(a, 3);
129     check(k5_json_get_tid(v) == K5_JSON_TID_NUMBER, "fmt array[3] tid");
130     check(k5_json_number_value(v) == 9, "fmt array[3] value");
131     v = k5_json_array_get(a, 4);
132     check(k5_json_get_tid(v) == K5_JSON_TID_NUMBER, "fmt array[4] tid");
133     check(k5_json_number_value(v) == -6, "fmt array[4] value");
134     v = k5_json_array_get(a, 5);
135     check(k5_json_get_tid(v) == K5_JSON_TID_STRING, "fmt array[5] tid");
136     check(strcmp(k5_json_string_utf8(v), "def") == 0, "fmt array[5] value");
137     v = k5_json_array_get(a, 6);
138     check(k5_json_get_tid(v) == K5_JSON_TID_NULL, "fmt array[6] tid");
139     v = k5_json_array_get(a, 7);
140     check(k5_json_get_tid(v) == K5_JSON_TID_STRING, "fmt array[7] tid");
141     check(strcmp(k5_json_string_utf8(v), "Z2hpag==") == 0,
142           "fmt array[7] value");
143     k5_json_release(v3);
144     k5_json_release(a);
145 }
146
147 static void
148 test_object(void)
149 {
150     k5_json_object object;
151     k5_json_number n, v1;
152     k5_json_string s, v2;
153
154     k5_json_object_create(&object);
155     k5_json_number_create(1, &v1);
156     k5_json_object_set(object, "key1", v1);
157     k5_json_string_create("hejsan", &v2);
158     k5_json_object_set(object, "key2", v2);
159
160     n = k5_json_object_get(object, "key1");
161     if (k5_json_number_value(n) != 1)
162         err("Retrieving key1 from object failed");
163
164     s = k5_json_object_get(object, "key2");
165     if (strcmp(k5_json_string_utf8(s), "hejsan") != 0)
166         err("Retrieving key2 from object failed");
167
168     check(k5_json_object_get(object, "key3") == NULL,
169           "object nonexistent key");
170
171     k5_json_object_set(object, "key1", NULL);
172     check(k5_json_object_get(object, "key1") == NULL,
173           "object removed key");
174     check(k5_json_object_get(object, "key2") != NULL,
175           "object remaining key");
176
177     k5_json_release(v1);
178     k5_json_release(v2);
179     k5_json_release(object);
180 }
181
182 static void
183 test_string(void)
184 {
185     k5_json_string s1, s2, s3;
186     unsigned char *data;
187     size_t len;
188
189     k5_json_string_create("hejsan", &s1);
190     k5_json_string_create("hejsan", &s2);
191     k5_json_string_create_base64("55555", 5, &s3);
192
193     if (strcmp(k5_json_string_utf8(s1), k5_json_string_utf8(s2)) != 0)
194         err("Identical strings are not identical");
195     if (strcmp(k5_json_string_utf8(s3), "NTU1NTU=") != 0)
196         err("base64 string has incorrect value");
197     k5_json_string_unbase64(s3, &data, &len);
198     if (len != 5 || memcmp(data, "55555", 5) != 0)
199         err("base64 string doesn't decode to correct value");
200     free(data);
201
202     k5_json_release(s1);
203     k5_json_release(s2);
204     k5_json_release(s3);
205 }
206
207 static void
208 test_json(void)
209 {
210     static char *tests[] = {
211         "{\"k1\":\"s1\",\"k2\":\"s2\"}",
212         "{\"k1\":[\"s1\",\"s2\",\"s3\"],\"k2\":\"s3\"}",
213         "{\"k1\":{\"k2\":\"s1\",\"k3\":\"s2\",\"k4\":\"s3\"},\"k5\":\"s4\"}",
214         "[\"v1\",\"v2\",[\"v3\",\"v4\",[\"v 5\",\" v 7 \"]],-123456789,"
215         "null,true,false,123456789,\"\"]",
216         "-1",
217         "\"\\\\abc\\\"\\nde\\b\\r/\\ff\\tghi\\u0001\\u001F\"",
218         "9223372036854775807",
219         "-9223372036854775808",
220         NULL
221     };
222     char **tptr, *s, *enc, *p, orig;
223     int i;
224     k5_json_value v, v2;
225
226     check(k5_json_decode("\"string\"", &v) == 0, "string1");
227     check(k5_json_get_tid(v) == K5_JSON_TID_STRING, "string1 tid");
228     check(strcmp(k5_json_string_utf8(v), "string") == 0, "string1 utf8");
229     k5_json_release(v);
230
231     check(k5_json_decode("\t \"foo\\\"bar\" ", &v) == 0, "string2");
232     check(k5_json_get_tid(v) == K5_JSON_TID_STRING, "string2 tid");
233     check(strcmp(k5_json_string_utf8(v), "foo\"bar") == 0, "string2 utf8");
234     k5_json_release(v);
235
236     check(k5_json_decode(" { \"key\" : \"value\" }", &v) == 0, "object1");
237     check(k5_json_get_tid(v) == K5_JSON_TID_OBJECT, "object1 tid");
238     v2 = k5_json_object_get(v, "key");
239     check(v2 != NULL, "object[key]");
240     check(k5_json_get_tid(v2) == K5_JSON_TID_STRING, "object1[key] tid");
241     check(strcmp(k5_json_string_utf8(v2), "value") == 0, "object1[key] utf8");
242     k5_json_release(v);
243
244     check(k5_json_decode("{ \"k1\" : { \"k2\" : \"s2\", \"k3\" : \"s3\" }, "
245                          "\"k4\" : \"s4\" }", &v) == 0, "object2");
246     v2 = k5_json_object_get(v, "k1");
247     check(v2 != NULL, "object2[k1]");
248     check(k5_json_get_tid(v2) == K5_JSON_TID_OBJECT, "object2[k1] tid");
249     v2 = k5_json_object_get(v2, "k3");
250     check(v2 != NULL, "object2[k1][k3]");
251     check(k5_json_get_tid(v2) == K5_JSON_TID_STRING, "object2[k1][k3] tid");
252     check(strcmp(k5_json_string_utf8(v2), "s3") == 0, "object2[k1][k3] utf8");
253     k5_json_release(v);
254
255     check(k5_json_decode("{ \"k1\" : 1 }", &v) == 0, "object3");
256     check(k5_json_get_tid(v) == K5_JSON_TID_OBJECT, "object3 id");
257     v2 = k5_json_object_get(v, "k1");
258     check(k5_json_get_tid(v2) == K5_JSON_TID_NUMBER, "object3[k1] tid");
259     check(k5_json_number_value(v2) == 1, "object3[k1] value");
260     k5_json_release(v);
261
262     check(k5_json_decode("-10", &v) == 0, "number1");
263     check(k5_json_get_tid(v) == K5_JSON_TID_NUMBER, "number1 tid");
264     check(k5_json_number_value(v) == -10, "number1 value");
265     k5_json_release(v);
266
267     check(k5_json_decode("99", &v) == 0, "number2");
268     check(k5_json_get_tid(v) == K5_JSON_TID_NUMBER, "number2 tid");
269     check(k5_json_number_value(v) == 99, "number2 value");
270     k5_json_release(v);
271
272     check(k5_json_decode(" [ 1 ]", &v) == 0, "array1");
273     check(k5_json_get_tid(v) == K5_JSON_TID_ARRAY, "array1 tid");
274     check(k5_json_array_length(v) == 1, "array1 len");
275     v2 = k5_json_array_get(v, 0);
276     check(v2 != NULL, "array1[0]");
277     check(k5_json_get_tid(v2) == K5_JSON_TID_NUMBER, "array1[0] tid");
278     check(k5_json_number_value(v2) == 1, "array1[0] value");
279     k5_json_release(v);
280
281     check(k5_json_decode(" [ -1 ]", &v) == 0, "array2");
282     check(k5_json_get_tid(v) == K5_JSON_TID_ARRAY, "array2 tid");
283     check(k5_json_array_length(v) == 1, "array2 len");
284     v2 = k5_json_array_get(v, 0);
285     check(v2 != NULL, "array2[0]");
286     check(k5_json_get_tid(v2) == K5_JSON_TID_NUMBER, "array2[0] tid");
287     check(k5_json_number_value(v2) == -1, "array2[0] value");
288     k5_json_release(v);
289
290     check(k5_json_decode("18446744073709551616", &v) == EOVERFLOW,
291           "unsigned 64-bit overflow");
292     check(k5_json_decode("9223372036854775808", &v) == EOVERFLOW,
293           "signed 64-bit positive overflow");
294     check(k5_json_decode("-9223372036854775809", &v) == EOVERFLOW,
295           "signed 64-bit negative overflow");
296
297     for (tptr = tests; *tptr != NULL; tptr++) {
298         s = strdup(*tptr);
299         if (k5_json_decode(s, &v))
300             err(s);
301         if (k5_json_encode(v, &enc) || strcmp(enc, s) != 0)
302             err(s);
303         free(enc);
304         k5_json_release(v);
305
306         /* Fuzz bytes.  Parsing may succeed or fail; we're just looking for
307          * memory access bugs. */
308         for (p = s; *p != '\0'; p++) {
309             orig = *p;
310             for (i = 0; i <= 255; i++) {
311                 *p = i;
312                 k5_json_decode(s, &v);
313                 k5_json_release(v);
314             }
315             *p = orig;
316         }
317         free(s);
318     }
319 }
320
321 int
322 main(int argc, char **argv)
323 {
324     test_array();
325     test_object();
326     test_string();
327     test_json();
328     return 0;
329 }