2 * Copyright 2023 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
10 #include "internal/json_enc.h"
11 #include "internal/nelem.h"
19 static int wbuf_flush(struct json_write_buf *wbuf, int full);
21 static int wbuf_init(struct json_write_buf *wbuf, BIO *bio, size_t alloc)
23 wbuf->buf = OPENSSL_malloc(alloc);
24 if (wbuf->buf == NULL)
33 static void wbuf_cleanup(struct json_write_buf *wbuf)
35 OPENSSL_free(wbuf->buf);
40 static void wbuf_set0_bio(struct json_write_buf *wbuf, BIO *bio)
45 /* Empty write buffer. */
46 static ossl_inline void wbuf_clean(struct json_write_buf *wbuf)
51 /* Available data remaining in buffer. */
52 static ossl_inline size_t wbuf_avail(struct json_write_buf *wbuf)
54 return wbuf->alloc - wbuf->cur;
57 /* Add character to write buffer, returning 0 on flush failure. */
58 static ossl_inline int wbuf_write_char(struct json_write_buf *wbuf, char c)
60 if (wbuf_avail(wbuf) == 0) {
61 if (!wbuf_flush(wbuf, /*full=*/0))
65 wbuf->buf[wbuf->cur++] = c;
70 * Write zero-terminated string to write buffer, returning 0 on flush failure.
72 static int wbuf_write_str(struct json_write_buf *wbuf, const char *s)
76 while ((c = *s++) != 0)
77 if (!wbuf_write_char(wbuf, c))
83 /* Flush write buffer, returning 0 on I/O failure. */
84 static int wbuf_flush(struct json_write_buf *wbuf, int full)
86 size_t written = 0, total_written = 0;
88 while (total_written < wbuf->cur) {
89 if (!BIO_write_ex(wbuf->bio,
90 wbuf->buf + total_written,
91 wbuf->cur - total_written,
94 wbuf->buf + total_written,
95 wbuf->cur - total_written);
100 total_written += written;
106 (void)BIO_flush(wbuf->bio); /* best effort */
112 * OSSL_JSON_ENC: Stack Management
113 * ===============================
116 static int json_ensure_stack_size(OSSL_JSON_ENC *json, size_t num_bytes)
118 unsigned char *stack;
120 if (json->stack_bytes >= num_bytes)
123 if (num_bytes <= OSSL_NELEM(json->stack_small)) {
124 stack = json->stack_small;
126 if (json->stack == json->stack_small)
129 stack = OPENSSL_realloc(json->stack, num_bytes);
135 json->stack_bytes = num_bytes;
139 /* Push one bit onto the stack. Returns 0 on allocation failure. */
140 static int json_push(OSSL_JSON_ENC *json, unsigned int v)
145 if (json->stack_end_byte >= json->stack_bytes) {
147 = (json->stack_bytes == 0)
148 ? OSSL_NELEM(json->stack_small)
149 : (json->stack_bytes * 2);
151 if (!json_ensure_stack_size(json, new_size))
154 json->stack_bytes = new_size;
158 json->stack[json->stack_end_byte] |= (v << json->stack_end_bit);
160 json->stack[json->stack_end_byte] &= ~(1U << json->stack_end_bit);
162 json->stack_end_bit = (json->stack_end_bit + 1) % CHAR_BIT;
163 if (json->stack_end_bit == 0)
164 ++json->stack_end_byte;
170 * Pop a bit from the stack. Returns 0 if stack is empty. Use json_peek() to get
171 * the value before calling this.
173 static int json_pop(OSSL_JSON_ENC *json)
175 if (json->stack_end_byte == 0 && json->stack_end_bit == 0)
178 if (json->stack_end_bit == 0) {
179 --json->stack_end_byte;
180 json->stack_end_bit = CHAR_BIT - 1;
182 --json->stack_end_bit;
189 * Returns the bit on the top of the stack, or -1 if the stack is empty.
191 static int json_peek(OSSL_JSON_ENC *json)
195 obyte = json->stack_end_byte;
196 obit = json->stack_end_bit;
207 return (json->stack[obyte] & (1U << obit)) != 0;
211 * OSSL_JSON_ENC: Initialisation
212 * =============================
221 static ossl_inline int in_ijson(const OSSL_JSON_ENC *json)
223 return (json->flags & OSSL_JSON_FLAG_IJSON) != 0;
226 static ossl_inline int in_seq(const OSSL_JSON_ENC *json)
228 return (json->flags & OSSL_JSON_FLAG_SEQ) != 0;
231 static ossl_inline int in_pretty(const OSSL_JSON_ENC *json)
233 return (json->flags & OSSL_JSON_FLAG_PRETTY) != 0;
236 int ossl_json_init(OSSL_JSON_ENC *json, BIO *bio, uint32_t flags)
238 memset(json, 0, sizeof(*json));
241 if (!wbuf_init(&json->wbuf, bio, 4096))
244 json->state = STATE_PRE_COMMA;
248 void ossl_json_cleanup(OSSL_JSON_ENC *json)
250 wbuf_cleanup(&json->wbuf);
252 if (json->stack != json->stack_small)
253 OPENSSL_free(json->stack);
258 int ossl_json_flush_cleanup(OSSL_JSON_ENC *json)
260 int ok = ossl_json_flush(json);
262 ossl_json_cleanup(json);
266 int ossl_json_reset(OSSL_JSON_ENC *json)
268 wbuf_clean(&json->wbuf);
269 json->stack_end_byte = 0;
270 json->stack_end_bit = 0;
275 int ossl_json_flush(OSSL_JSON_ENC *json)
277 return wbuf_flush(&json->wbuf, /*full=*/1);
280 int ossl_json_set0_sink(OSSL_JSON_ENC *json, BIO *bio)
282 wbuf_set0_bio(&json->wbuf, bio);
286 int ossl_json_in_error(OSSL_JSON_ENC *json)
296 static void json_write_qstring(OSSL_JSON_ENC *json, const char *str);
297 static void json_indent(OSSL_JSON_ENC *json);
299 static void json_raise_error(OSSL_JSON_ENC *json)
304 static void json_undefer(OSSL_JSON_ENC *json)
306 if (!json->defer_indent)
312 static void json_write_char(OSSL_JSON_ENC *json, char ch)
314 if (ossl_json_in_error(json))
318 if (!wbuf_write_char(&json->wbuf, ch))
319 json_raise_error(json);
322 static void json_write_str(OSSL_JSON_ENC *json, const char *s)
324 if (ossl_json_in_error(json))
328 if (!wbuf_write_str(&json->wbuf, s))
329 json_raise_error(json);
332 static void json_indent(OSSL_JSON_ENC *json)
336 json->defer_indent = 0;
338 if (!in_pretty(json))
341 json_write_char(json, '\n');
343 depth = json->stack_end_byte * 8 + json->stack_end_bit;
344 for (i = 0; i < depth * 4; ++i)
345 json_write_str(json, " ");
348 static int json_pre_item(OSSL_JSON_ENC *json)
352 if (ossl_json_in_error(json))
355 switch (json->state) {
356 case STATE_PRE_COMMA:
360 json_raise_error(json);
365 json_write_char(json, ',');
366 if (ossl_json_in_error(json))
372 if (s < 0 && in_seq(json))
373 json_write_char(json, '\x1E');
375 json->state = STATE_PRE_ITEM;
383 json_raise_error(json);
390 static void json_post_item(OSSL_JSON_ENC *json)
392 int s = json_peek(json);
394 json->state = STATE_PRE_COMMA;
396 if (s < 0 && in_seq(json))
397 json_write_char(json, '\n');
401 * Begin a composite structure (object or array).
403 * type: 0=object, 1=array.
405 static void composite_begin(OSSL_JSON_ENC *json, int type, char ch)
407 if (!json_pre_item(json)
408 || !json_push(json, type))
409 json_raise_error(json);
411 json_write_char(json, ch);
412 json->defer_indent = 1;
416 * End a composite structure (object or array).
418 * type: 0=object, 1=array. Errors on mismatch.
420 static void composite_end(OSSL_JSON_ENC *json, int type, char ch)
422 int was_defer = json->defer_indent;
424 if (ossl_json_in_error(json))
427 json->defer_indent = 0;
429 if (json_peek(json) != type) {
430 json_raise_error(json);
434 if (type == 0 && json->state == STATE_PRE_ITEM) {
435 json_raise_error(json);
439 if (!json_pop(json)) {
440 json_raise_error(json);
447 json_write_char(json, ch);
448 json_post_item(json);
451 /* Begin a new JSON object. */
452 void ossl_json_object_begin(OSSL_JSON_ENC *json)
454 composite_begin(json, 0, '{');
455 json->state = STATE_PRE_KEY;
458 /* End a JSON object. Must be matched with a call to ossl_json_object_begin(). */
459 void ossl_json_object_end(OSSL_JSON_ENC *json)
461 composite_end(json, 0, '}');
464 /* Begin a new JSON array. */
465 void ossl_json_array_begin(OSSL_JSON_ENC *json)
467 composite_begin(json, 1, '[');
468 json->state = STATE_PRE_ITEM;
471 /* End a JSON array. Must be matched with a call to ossl_json_array_begin(). */
472 void ossl_json_array_end(OSSL_JSON_ENC *json)
474 composite_end(json, 1, ']');
478 * Encode a JSON key within an object. Pass a zero-terminated string, which can
479 * be freed immediately following the call to this function.
481 void ossl_json_key(OSSL_JSON_ENC *json, const char *key)
483 if (ossl_json_in_error(json))
486 if (json_peek(json) != 0) {
488 json_raise_error(json);
492 if (json->state == STATE_PRE_COMMA) {
493 json_write_char(json, ',');
494 json->state = STATE_PRE_KEY;
498 if (json->state != STATE_PRE_KEY) {
499 json_raise_error(json);
503 json_write_qstring(json, key);
504 if (ossl_json_in_error(json))
507 json_write_char(json, ':');
509 json_write_char(json, ' ');
511 json->state = STATE_PRE_ITEM;
514 /* Encode a JSON 'null' value. */
515 void ossl_json_null(OSSL_JSON_ENC *json)
517 if (!json_pre_item(json))
520 json_write_str(json, "null");
521 json_post_item(json);
524 void ossl_json_bool(OSSL_JSON_ENC *json, int v)
526 if (!json_pre_item(json))
529 json_write_str(json, v > 0 ? "true" : "false");
530 json_post_item(json);
533 #define POW_53 (((int64_t)1) << 53)
535 /* Encode a JSON integer from a uint64_t. */
536 static void json_u64(OSSL_JSON_ENC *json, uint64_t v, int noquote)
538 char buf[22], *p = buf + sizeof(buf) - 1;
539 int quote = !noquote && in_ijson(json) && v > (uint64_t)(POW_53 - 1);
541 if (!json_pre_item(json))
545 json_write_char(json, '"');
550 for (*p = '\0'; v > 0; v /= 10)
553 json_write_str(json, p);
556 json_write_char(json, '"');
558 json_post_item(json);
561 void ossl_json_u64(OSSL_JSON_ENC *json, uint64_t v)
563 json_u64(json, v, 0);
566 /* Encode a JSON integer from an int64_t. */
567 void ossl_json_i64(OSSL_JSON_ENC *json, int64_t value)
573 ossl_json_u64(json, (uint64_t)value);
577 if (!json_pre_item(json))
580 quote = in_ijson(json)
581 && (value > POW_53 - 1 || value < -POW_53 + 1);
584 json_write_char(json, '"');
586 json_write_char(json, '-');
588 uv = (value == INT64_MIN)
589 ? ((uint64_t)-(INT64_MIN + 1)) + 1
591 json_u64(json, uv, /*noquote=*/1);
593 if (quote && !ossl_json_in_error(json))
594 json_write_char(json, '"');
597 /* Encode a JSON number from a 64-bit floating point value. */
598 void ossl_json_f64(OSSL_JSON_ENC *json, double value)
602 if (!json_pre_item(json))
605 if (isnan(value) || isinf(value)) {
606 json_raise_error(json);
610 BIO_snprintf(buf, sizeof(buf), "%1.17g", value);
611 json_write_str(json, buf);
612 json_post_item(json);
616 * Encode a JSON UTF-8 string from a zero-terminated string. The string passed
617 * can be freed immediately following the call to this function.
619 static ossl_inline int hex_digit(int v)
621 return v >= 10 ? 'a' + (v - 10) : '0' + v;
624 static ossl_inline void
625 json_write_qstring_inner(OSSL_JSON_ENC *json, const char *str, size_t str_len,
632 if (ossl_json_in_error(json))
635 json_write_char(json, '"');
637 for (j = 0; (nul_term && *str != '\0')
638 || (!nul_term && j < str_len); ++str, ++j) {
641 case '\n': o = "\\n"; break;
642 case '\r': o = "\\r"; break;
643 case '\t': o = "\\t"; break;
644 case '\b': o = "\\b"; break;
645 case '\f': o = "\\f"; break;
646 case '"': o = "\\\""; break;
647 case '\\': o = "\\\\"; break;
649 if ((unsigned char)c >= 0x80) {
650 json_raise_error(json);
653 if ((unsigned char)c < 0x20 || (unsigned char)c >= 0x7f) {
656 for (i = 0; i < 4; ++i)
657 obuf[2 + i] = hex_digit((c >> ((3 - i) * 4)) & 0x0F);
661 json_write_char(json, c);
667 json_write_str(json, o);
670 json_write_char(json, '"');
674 json_write_qstring(OSSL_JSON_ENC *json, const char *str)
676 json_write_qstring_inner(json, str, 0, 1);
680 json_write_qstring_len(OSSL_JSON_ENC *json, const char *str, size_t str_len)
682 json_write_qstring_inner(json, str, str_len, 0);
685 void ossl_json_str(OSSL_JSON_ENC *json, const char *str)
687 if (!json_pre_item(json))
690 json_write_qstring(json, str);
691 json_post_item(json);
694 void ossl_json_str_len(OSSL_JSON_ENC *json, const char *str, size_t str_len)
696 if (!json_pre_item(json))
699 json_write_qstring_len(json, str, str_len);
700 json_post_item(json);
704 * Encode binary data as a lowercase hex string. data_len is the data length in
707 void ossl_json_str_hex(OSSL_JSON_ENC *json, const void *data, size_t data_len)
709 const unsigned char *b = data, *end = b + data_len;
712 if (!json_pre_item(json))
715 json_write_char(json, '"');
717 for (; b < end; ++b) {
719 json_write_char(json, hex_digit(c >> 4));
720 json_write_char(json, hex_digit(c & 0x0F));
723 json_write_char(json, '"');
724 json_post_item(json);