2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
14 #include "internal/json_enc.h"
23 static int helper_ensure(struct helper *h)
28 if (!TEST_ptr(h->mem_bio = BIO_new(BIO_s_mem())))
31 if (!ossl_json_init(&h->j, h->mem_bio, h->flags)) {
32 BIO_free_all(h->mem_bio);
41 static void helper_cleanup(struct helper *h)
43 BIO_free_all(h->mem_bio);
47 ossl_json_cleanup(&h->j);
52 static void helper_set_flags(struct helper *h, uint32_t flags)
66 #define OP_P(x) { (x) },
67 #define OP_U64(x) { NULL, (x) },
68 #define OP_I64(x) { NULL, 0, (x) },
69 #define OP_D(x) { NULL, 0, 0, (x) },
70 #define OP_FP(x) { NULL, 0, 0, 0, (void (*)(void))(x) },
73 const char *name, *title;
74 const struct script_word *words;
76 const char *expected_output;
77 size_t expected_output_len;
80 typedef const struct script_info *(*info_func)(void);
84 OPK_CALL, /* (OSSL_JSON_ENC *) */
85 OPK_CALL_P, /* (OSSL_JSON_ENC *, const void *) */
86 OPK_CALL_I, /* (OSSL_JSON_ENC *, int) */
87 OPK_CALL_U64, /* (OSSL_JSON_ENC *, uint64_t) */
88 OPK_CALL_I64, /* (OSSL_JSON_ENC *, int64_t) */
89 OPK_CALL_D, /* (OSSL_JSON_ENC *, double) */
90 OPK_CALL_PZ, /* (OSSL_JSON_ENC *, const void *, size_t) */
91 OPK_ASSERT_ERROR, /* (OSSL_JSON_ENC *, int expect_error) */
92 OPK_INIT_FLAGS /* (uint32_t flags) */
95 typedef void (*fp_type)(OSSL_JSON_ENC *);
96 typedef void (*fp_p_type)(OSSL_JSON_ENC *, const void *);
97 typedef void (*fp_i_type)(OSSL_JSON_ENC *, int);
98 typedef void (*fp_u64_type)(OSSL_JSON_ENC *, uint64_t);
99 typedef void (*fp_i64_type)(OSSL_JSON_ENC *, int64_t);
100 typedef void (*fp_d_type)(OSSL_JSON_ENC *, double);
101 typedef void (*fp_pz_type)(OSSL_JSON_ENC *, const void *, size_t);
103 #define OP_END() OP_U64(OPK_END)
104 #define OP_CALL(f) OP_U64(OPK_CALL) OP_FP(f)
105 #define OP_CALL_P(f, x) OP_U64(OPK_CALL_P) OP_FP(f) OP_P (x)
106 #define OP_CALL_I(f, x) OP_U64(OPK_CALL_I) OP_FP(f) OP_I64(x)
107 #define OP_CALL_U64(f, x) OP_U64(OPK_CALL_U64) OP_FP(f) OP_U64(x)
108 #define OP_CALL_I64(f, x) OP_U64(OPK_CALL_I64) OP_FP(f) OP_I64(x)
109 #define OP_CALL_D(f, x) OP_U64(OPK_CALL_D) OP_FP(f) OP_D (x)
110 #define OP_CALL_PZ(f, x, xl) OP_U64(OPK_CALL_PZ) OP_FP(f) OP_P (x) OP_U64(xl)
111 #define OP_ASSERT_ERROR(err) OP_U64(OPK_ASSERT_ERROR) OP_U64(err)
112 #define OP_INIT_FLAGS(flags) OP_U64(OPK_INIT_FLAGS) OP_U64(flags)
114 #define OPJ_BEGIN_O() OP_CALL(ossl_json_object_begin)
115 #define OPJ_END_O() OP_CALL(ossl_json_object_end)
116 #define OPJ_BEGIN_A() OP_CALL(ossl_json_array_begin)
117 #define OPJ_END_A() OP_CALL(ossl_json_array_end)
118 #define OPJ_NULL() OP_CALL(ossl_json_null)
119 #define OPJ_BOOL(x) OP_CALL_I(ossl_json_bool, (x))
120 #define OPJ_U64(x) OP_CALL_U64(ossl_json_u64, (x))
121 #define OPJ_I64(x) OP_CALL_I64(ossl_json_i64, (x))
122 #define OPJ_F64(x) OP_CALL_D(ossl_json_f64, (x))
123 #define OPJ_KEY(x) OP_CALL_P(ossl_json_key, (x))
124 #define OPJ_STR(x) OP_CALL_P(ossl_json_str, (x))
125 #define OPJ_STR_LEN(x, xl) OP_CALL_PZ(ossl_json_str_len, (x), (xl))
126 #define OPJ_STR_HEX(x, xl) OP_CALL_PZ(ossl_json_str_hex, (x), (xl))
128 #define BEGIN_SCRIPT(name, title, flags) \
129 static const struct script_info *get_script_##name(void) \
131 static const char script_name[] = #name; \
132 static const char script_title[] = #title; \
134 static const struct script_word script_words[] = { \
137 #define END_SCRIPT_EXPECTING(s, slen) \
140 static const struct script_info script_info = { \
141 script_name, script_title, script_words, OSSL_NELEM(script_words), \
144 return &script_info; \
147 #ifdef OPENSSL_SYS_VMS
149 * The VMS C compiler recognises \u in strings, and emits a warning, which
150 * stops the build. Because we think we know what we're doing, we change that
151 * particular message to be merely informational.
153 # pragma message informational UCNNOMAP
156 #define END_SCRIPT_EXPECTING_S(s) END_SCRIPT_EXPECTING(s, SIZE_MAX)
157 #define END_SCRIPT_EXPECTING_Q(s) END_SCRIPT_EXPECTING(#s, sizeof(#s) - 1)
159 #define SCRIPT(name) get_script_##name,
161 BEGIN_SCRIPT(null, "serialize a single null", 0)
163 END_SCRIPT_EXPECTING_Q(null)
165 BEGIN_SCRIPT(obj_empty, "serialize an empty object", 0)
168 END_SCRIPT_EXPECTING_Q({})
170 BEGIN_SCRIPT(array_empty, "serialize an empty array", 0)
173 END_SCRIPT_EXPECTING_Q([])
175 BEGIN_SCRIPT(bool_false, "serialize false", 0)
177 END_SCRIPT_EXPECTING_Q(false)
179 BEGIN_SCRIPT(bool_true, "serialize true", 0)
181 END_SCRIPT_EXPECTING_Q(true)
183 BEGIN_SCRIPT(u64_0, "serialize u64(0)", 0)
185 END_SCRIPT_EXPECTING_Q(0)
187 BEGIN_SCRIPT(u64_1, "serialize u64(1)", 0)
189 END_SCRIPT_EXPECTING_Q(1)
191 BEGIN_SCRIPT(u64_10, "serialize u64(10)", 0)
193 END_SCRIPT_EXPECTING_Q(10)
195 BEGIN_SCRIPT(u64_12345, "serialize u64(12345)", 0)
197 END_SCRIPT_EXPECTING_Q(12345)
199 BEGIN_SCRIPT(u64_18446744073709551615, "serialize u64(18446744073709551615)", 0)
200 OPJ_U64(18446744073709551615ULL)
201 END_SCRIPT_EXPECTING_Q(18446744073709551615)
203 BEGIN_SCRIPT(i64_0, "serialize i64(0)", 0)
205 END_SCRIPT_EXPECTING_Q(0)
207 BEGIN_SCRIPT(i64_1, "serialize i64(1)", 0)
209 END_SCRIPT_EXPECTING_Q(1)
211 BEGIN_SCRIPT(i64_2, "serialize i64(2)", 0)
213 END_SCRIPT_EXPECTING_Q(2)
215 BEGIN_SCRIPT(i64_10, "serialize i64(10)", 0)
217 END_SCRIPT_EXPECTING_Q(10)
219 BEGIN_SCRIPT(i64_12345, "serialize i64(12345)", 0)
221 END_SCRIPT_EXPECTING_Q(12345)
223 BEGIN_SCRIPT(i64_9223372036854775807, "serialize i64(9223372036854775807)", 0)
224 OPJ_I64(9223372036854775807LL)
225 END_SCRIPT_EXPECTING_Q(9223372036854775807)
227 BEGIN_SCRIPT(i64_m1, "serialize i64(-1)", 0)
229 END_SCRIPT_EXPECTING_Q(-1)
231 BEGIN_SCRIPT(i64_m2, "serialize i64(-2)", 0)
233 END_SCRIPT_EXPECTING_Q(-2)
235 BEGIN_SCRIPT(i64_m10, "serialize i64(-10)", 0)
237 END_SCRIPT_EXPECTING_Q(-10)
239 BEGIN_SCRIPT(i64_m12345, "serialize i64(-12345)", 0)
241 END_SCRIPT_EXPECTING_Q(-12345)
243 BEGIN_SCRIPT(i64_m9223372036854775807, "serialize i64(-9223372036854775807)", 0)
244 OPJ_I64(-9223372036854775807LL)
245 END_SCRIPT_EXPECTING_Q(-9223372036854775807)
247 BEGIN_SCRIPT(i64_m9223372036854775808, "serialize i64(-9223372036854775808)", 0)
248 OPJ_I64(-9223372036854775807LL - 1LL)
249 END_SCRIPT_EXPECTING_Q(-9223372036854775808)
251 BEGIN_SCRIPT(str_empty, "serialize \"\"", 0)
253 END_SCRIPT_EXPECTING_Q("")
255 BEGIN_SCRIPT(str_a, "serialize \"a\"", 0)
257 END_SCRIPT_EXPECTING_Q("a")
259 BEGIN_SCRIPT(str_abc, "serialize \"abc\"", 0)
261 END_SCRIPT_EXPECTING_Q("abc")
263 BEGIN_SCRIPT(str_quote, "serialize with quote", 0)
265 END_SCRIPT_EXPECTING_Q("abc\"def")
267 BEGIN_SCRIPT(str_quote2, "serialize with quote", 0)
268 OPJ_STR("abc\"\"def")
269 END_SCRIPT_EXPECTING_Q("abc\"\"def")
271 BEGIN_SCRIPT(str_escape, "serialize with various escapes", 0)
272 OPJ_STR("abc\"\"de'f\r\n\t\b\f\\\x01\v\x7f\\")
273 END_SCRIPT_EXPECTING_Q("abc\"\"de'f\r\n\t\b\f\\\u0001\u000b\u007f\\")
275 BEGIN_SCRIPT(str_len, "length-signalled string", 0)
276 OPJ_STR_LEN("abcdef", 6)
277 END_SCRIPT_EXPECTING_Q("abcdef")
279 BEGIN_SCRIPT(str_len0, "0-length-signalled string", 0)
281 END_SCRIPT_EXPECTING_Q("")
283 BEGIN_SCRIPT(str_len_nul, "string with NUL", 0)
284 OPJ_STR_LEN("x\0y", 3)
285 END_SCRIPT_EXPECTING_Q("x\u0000y")
287 BEGIN_SCRIPT(hex_data0, "zero-length hex data", 0)
289 END_SCRIPT_EXPECTING_Q("")
291 BEGIN_SCRIPT(hex_data, "hex data", 0)
292 OPJ_STR_HEX("\x00\x01\x5a\xfb\xff", 5)
293 END_SCRIPT_EXPECTING_Q("00015afbff")
295 BEGIN_SCRIPT(array_nest1, "serialize nested empty arrays", 0)
300 END_SCRIPT_EXPECTING_Q([[]])
302 BEGIN_SCRIPT(array_nest2, "serialize nested empty arrays", 0)
309 END_SCRIPT_EXPECTING_Q([[[]]])
311 BEGIN_SCRIPT(array_nest3, "serialize nested empty arrays", 0)
324 END_SCRIPT_EXPECTING_S("[[[],[],[]],[]]")
326 BEGIN_SCRIPT(array_nest4, "deep nested arrays", 0)
368 END_SCRIPT_EXPECTING_S("[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]],null]")
370 BEGIN_SCRIPT(obj_nontrivial1, "serialize nontrivial object", 0)
375 END_SCRIPT_EXPECTING_S("{\"\":null}")
377 BEGIN_SCRIPT(obj_nontrivial2, "serialize nontrivial object", 0)
384 END_SCRIPT_EXPECTING_S("{\"\":null,\"x\":null}")
386 BEGIN_SCRIPT(obj_nest1, "serialize nested objects", 0)
408 END_SCRIPT_EXPECTING_S("{\"\":{\"x\":42},\"x\":[42,101],\"y\":null,\"z\":{\"z0\":-1,\"z1\":-2}}")
410 BEGIN_SCRIPT(err_obj_no_key, "error test: object item without key", 0)
417 END_SCRIPT_EXPECTING_S("{")
419 BEGIN_SCRIPT(err_obj_multi_key, "error test: object item with repeated key", 0)
427 END_SCRIPT_EXPECTING_S("{\"x\":")
429 BEGIN_SCRIPT(err_obj_no_value, "error test: object item with no value", 0)
435 END_SCRIPT_EXPECTING_S("{\"x\":")
437 BEGIN_SCRIPT(err_utf8, "error test: only basic ASCII supported", 0)
440 END_SCRIPT_EXPECTING_S("\"\\u0080\"")
442 BEGIN_SCRIPT(utf8_2, "test: valid UTF-8 2byte supported", 0)
443 OPJ_STR("low=\xc2\x80, high=\xdf\xbf")
445 END_SCRIPT_EXPECTING_S("\"low=\xc2\x80, high=\xdf\xbf\"")
447 BEGIN_SCRIPT(utf8_3, "test: valid UTF-8 3byte supported", 0)
448 OPJ_STR("low=\xe0\xa0\x80, high=\xef\xbf\xbf")
450 END_SCRIPT_EXPECTING_S("\"low=\xe0\xa0\x80, high=\xef\xbf\xbf\"")
452 BEGIN_SCRIPT(utf8_4, "test: valid UTF-8 4byte supported", 0)
453 OPJ_STR("low=\xf0\x90\xbf\xbf, high=\xf4\x8f\xbf\xbf")
455 END_SCRIPT_EXPECTING_S("\"low=\xf0\x90\xbf\xbf, high=\xf4\x8f\xbf\xbf\"")
457 BEGIN_SCRIPT(ijson_int, "I-JSON: large integer", OSSL_JSON_FLAG_IJSON)
461 OPJ_U64(9007199254740991)
462 OPJ_U64(9007199254740992)
463 OPJ_I64(-9007199254740991)
464 OPJ_I64(-9007199254740992)
466 END_SCRIPT_EXPECTING_S("[1,-1,9007199254740991,\"9007199254740992\",-9007199254740991,\"-9007199254740992\"]")
468 BEGIN_SCRIPT(multi_item, "multiple top level items", 0)
475 END_SCRIPT_EXPECTING_S("nullnull[][]")
477 BEGIN_SCRIPT(seq, "JSON-SEQ", OSSL_JSON_FLAG_SEQ)
488 END_SCRIPT_EXPECTING_S("\x1Enull\n" "\x1Enull\n" "\x1Enull\n" "\x1E{\"x\":1,\"y\":{}}\n")
490 static const info_func scripts[] = {
500 SCRIPT(u64_18446744073709551615)
506 SCRIPT(i64_9223372036854775807)
511 SCRIPT(i64_m9223372036854775807)
512 SCRIPT(i64_m9223372036854775808)
528 SCRIPT(obj_nontrivial1)
529 SCRIPT(obj_nontrivial2)
531 SCRIPT(err_obj_no_key)
532 SCRIPT(err_obj_multi_key)
533 SCRIPT(err_obj_no_value)
544 static int run_script(const struct script_info *info)
546 int ok = 0, asserted = -1;
547 const struct script_word *words = info->words;
549 struct script_word w;
550 struct helper h = {0};
551 BUF_MEM *bufp = NULL;
553 TEST_info("running script '%s' (%s)", info->name, info->title);
555 #define GET_WORD() (w = words[wp++])
556 #define GET_U64() (GET_WORD().u64)
557 #define GET_I64() (GET_WORD().i64)
558 #define GET_FP() (GET_WORD().fp)
559 #define GET_P() (GET_WORD().p)
566 helper_set_flags(&h, (uint32_t)GET_U64());
570 fp_type f = (fp_type)GET_FP();
572 if (!TEST_true(helper_ensure(&h)))
580 fp_i_type f = (fp_i_type)GET_FP();
582 if (!TEST_true(helper_ensure(&h)))
585 f(&h.j, (int)GET_I64());
590 fp_u64_type f = (fp_u64_type)GET_FP();
592 if (!TEST_true(helper_ensure(&h)))
600 fp_i64_type f = (fp_i64_type)GET_FP();
602 if (!TEST_true(helper_ensure(&h)))
610 fp_p_type f = (fp_p_type)GET_FP();
612 if (!TEST_true(helper_ensure(&h)))
620 fp_pz_type f = (fp_pz_type)GET_FP();
624 if (!TEST_true(helper_ensure(&h)))
629 f(&h.j, p, (size_t)u64);
632 case OPK_ASSERT_ERROR:
634 if (!TEST_true(helper_ensure(&h)))
637 asserted = (int)GET_U64();
638 if (!TEST_int_eq(ossl_json_in_error(&h.j), asserted))
643 #define OP_ASSERT_ERROR(err) OP_U64(OPK_ASSERT_ERROR) OP_U64(err)
646 TEST_error("unknown opcode");
651 if (!TEST_true(helper_ensure(&h)))
654 if (!TEST_true(ossl_json_flush(&h.j)))
657 /* Implicit error check if not done explicitly. */
658 if (asserted < 0 && !TEST_false(ossl_json_in_error(&h.j)))
661 if (!TEST_true(BIO_get_mem_ptr(h.mem_bio, &bufp)))
664 if (!TEST_mem_eq(bufp->data, bufp->length,
665 info->expected_output,
666 info->expected_output_len == SIZE_MAX
667 ? strlen(info->expected_output)
668 : info->expected_output_len))
674 TEST_error("script '%s' failed", info->name);
680 static int test_json_enc(void)
685 for (i = 0; i < OSSL_NELEM(scripts); ++i)
686 if (!TEST_true(run_script(scripts[i]())))
692 int setup_tests(void)
694 ADD_TEST(test_json_enc);