Coverage Report

Created: 2024-07-27 06:39

/src/openssl/ssl/quic/json_enc.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
3
 *
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
8
 */
9
10
#include "internal/json_enc.h"
11
#include "internal/nelem.h"
12
#include "internal/numbers.h"
13
#include <string.h>
14
#include <math.h>
15
16
/*
17
 * wbuf
18
 * ====
19
 */
20
static int wbuf_flush(struct json_write_buf *wbuf, int full);
21
22
static int wbuf_init(struct json_write_buf *wbuf, BIO *bio, size_t alloc)
23
0
{
24
0
    wbuf->buf = OPENSSL_malloc(alloc);
25
0
    if (wbuf->buf == NULL)
26
0
        return 0;
27
28
0
    wbuf->cur   = 0;
29
0
    wbuf->alloc = alloc;
30
0
    wbuf->bio   = bio;
31
0
    return 1;
32
0
}
33
34
static void wbuf_cleanup(struct json_write_buf *wbuf)
35
0
{
36
0
    OPENSSL_free(wbuf->buf);
37
0
    wbuf->buf   = NULL;
38
0
    wbuf->alloc = 0;
39
0
}
40
41
static void wbuf_set0_bio(struct json_write_buf *wbuf, BIO *bio)
42
0
{
43
0
    wbuf->bio = bio;
44
0
}
45
46
/* Empty write buffer. */
47
static ossl_inline void wbuf_clean(struct json_write_buf *wbuf)
48
0
{
49
0
    wbuf->cur = 0;
50
0
}
51
52
/* Available data remaining in buffer. */
53
static ossl_inline size_t wbuf_avail(struct json_write_buf *wbuf)
54
0
{
55
0
    return wbuf->alloc - wbuf->cur;
56
0
}
57
58
/* Add character to write buffer, returning 0 on flush failure. */
59
static ossl_inline int wbuf_write_char(struct json_write_buf *wbuf, char c)
60
0
{
61
0
    if (wbuf_avail(wbuf) == 0) {
62
0
        if (!wbuf_flush(wbuf, /*full=*/0))
63
0
            return 0;
64
0
    }
65
66
0
    wbuf->buf[wbuf->cur++] = c;
67
0
    return 1;
68
0
}
69
70
/*
71
 * Write zero-terminated string to write buffer, returning 0 on flush failure.
72
 */
73
static int wbuf_write_str(struct json_write_buf *wbuf, const char *s)
74
0
{
75
0
    char c;
76
77
0
    while ((c = *s++) != 0)
78
0
        if (!wbuf_write_char(wbuf, c))
79
0
            return 0;
80
81
0
    return 1;
82
0
}
83
84
/* Flush write buffer, returning 0 on I/O failure. */
85
static int wbuf_flush(struct json_write_buf *wbuf, int full)
86
0
{
87
0
    size_t written = 0, total_written = 0;
88
89
0
    while (total_written < wbuf->cur) {
90
0
        if (!BIO_write_ex(wbuf->bio,
91
0
                          wbuf->buf + total_written,
92
0
                          wbuf->cur - total_written,
93
0
                          &written)) {
94
0
            memmove(wbuf->buf,
95
0
                    wbuf->buf + total_written,
96
0
                    wbuf->cur - total_written);
97
0
            wbuf->cur = 0;
98
0
            return 0;
99
0
        }
100
101
0
        total_written += written;
102
0
    }
103
104
0
    wbuf->cur = 0;
105
106
0
    if (full)
107
0
        (void)BIO_flush(wbuf->bio); /* best effort */
108
109
0
    return 1;
110
0
}
111
112
/*
113
 * OSSL_JSON_ENC: Stack Management
114
 * ===============================
115
 */
116
117
static int json_ensure_stack_size(OSSL_JSON_ENC *json, size_t num_bytes)
118
0
{
119
0
    unsigned char *stack;
120
121
0
    if (json->stack_bytes >= num_bytes)
122
0
        return 1;
123
124
0
    if (num_bytes <= OSSL_NELEM(json->stack_small)) {
125
0
        stack = json->stack_small;
126
0
    } else {
127
0
        if (json->stack == json->stack_small)
128
0
            json->stack = NULL;
129
130
0
        stack = OPENSSL_realloc(json->stack, num_bytes);
131
0
        if (stack == NULL)
132
0
            return 0;
133
0
    }
134
135
0
    json->stack         = stack;
136
0
    json->stack_bytes   = num_bytes;
137
0
    return 1;
138
0
}
139
140
/* Push one bit onto the stack. Returns 0 on allocation failure. */
141
static int json_push(OSSL_JSON_ENC *json, unsigned int v)
142
0
{
143
0
    if (v > 1)
144
0
        return 0;
145
146
0
    if (json->stack_end_byte >= json->stack_bytes) {
147
0
        size_t new_size
148
0
            = (json->stack_bytes == 0)
149
0
            ? OSSL_NELEM(json->stack_small)
150
0
            : (json->stack_bytes * 2);
151
152
0
        if (!json_ensure_stack_size(json, new_size))
153
0
            return 0;
154
155
0
        json->stack_bytes = new_size;
156
0
    }
157
158
0
    if (v > 0)
159
0
        json->stack[json->stack_end_byte] |= (v << json->stack_end_bit);
160
0
    else
161
0
        json->stack[json->stack_end_byte] &= ~(1U << json->stack_end_bit);
162
163
0
    json->stack_end_bit = (json->stack_end_bit + 1) % CHAR_BIT;
164
0
    if (json->stack_end_bit == 0)
165
0
        ++json->stack_end_byte;
166
167
0
    return 1;
168
0
}
169
170
/*
171
 * Pop a bit from the stack. Returns 0 if stack is empty. Use json_peek() to get
172
 * the value before calling this.
173
 */
174
static int json_pop(OSSL_JSON_ENC *json)
175
0
{
176
0
    if (json->stack_end_byte == 0 && json->stack_end_bit == 0)
177
0
        return 0;
178
179
0
    if (json->stack_end_bit == 0) {
180
0
        --json->stack_end_byte;
181
0
        json->stack_end_bit = CHAR_BIT - 1;
182
0
    } else {
183
0
        --json->stack_end_bit;
184
0
    }
185
186
0
    return 1;
187
0
}
188
189
/*
190
 * Returns the bit on the top of the stack, or -1 if the stack is empty.
191
 */
192
static int json_peek(OSSL_JSON_ENC *json)
193
0
{
194
0
    size_t obyte, obit;
195
196
0
    obyte = json->stack_end_byte;
197
0
    obit  = json->stack_end_bit;
198
0
    if (obit == 0) {
199
0
       if (obyte == 0)
200
0
           return -1;
201
202
0
        --obyte;
203
0
        obit = CHAR_BIT - 1;
204
0
    } else {
205
0
        --obit;
206
0
    }
207
208
0
    return (json->stack[obyte] & (1U << obit)) != 0;
209
0
}
210
211
/*
212
 * OSSL_JSON_ENC: Initialisation
213
 * =============================
214
 */
215
216
enum {
217
    STATE_PRE_KEY,
218
    STATE_PRE_ITEM,
219
    STATE_PRE_COMMA
220
};
221
222
static ossl_inline int in_ijson(const OSSL_JSON_ENC *json)
223
0
{
224
0
    return (json->flags & OSSL_JSON_FLAG_IJSON) != 0;
225
0
}
226
227
static ossl_inline int in_seq(const OSSL_JSON_ENC *json)
228
0
{
229
0
    return (json->flags & OSSL_JSON_FLAG_SEQ) != 0;
230
0
}
231
232
static ossl_inline int in_pretty(const OSSL_JSON_ENC *json)
233
0
{
234
0
    return (json->flags & OSSL_JSON_FLAG_PRETTY) != 0;
235
0
}
236
237
int ossl_json_init(OSSL_JSON_ENC *json, BIO *bio, uint32_t flags)
238
0
{
239
0
    memset(json, 0, sizeof(*json));
240
0
    json->flags     = flags;
241
0
    json->error     = 0;
242
0
    if (!wbuf_init(&json->wbuf, bio, 4096))
243
0
        return 0;
244
245
0
    json->state = STATE_PRE_COMMA;
246
0
    return 1;
247
0
}
248
249
void ossl_json_cleanup(OSSL_JSON_ENC *json)
250
0
{
251
0
    wbuf_cleanup(&json->wbuf);
252
253
0
    if (json->stack != json->stack_small)
254
0
        OPENSSL_free(json->stack);
255
256
0
    json->stack = NULL;
257
0
}
258
259
int ossl_json_flush_cleanup(OSSL_JSON_ENC *json)
260
0
{
261
0
    int ok = ossl_json_flush(json);
262
263
0
    ossl_json_cleanup(json);
264
0
    return ok;
265
0
}
266
267
int ossl_json_reset(OSSL_JSON_ENC *json)
268
0
{
269
0
    wbuf_clean(&json->wbuf);
270
0
    json->stack_end_byte    = 0;
271
0
    json->stack_end_bit     = 0;
272
0
    json->error             = 0;
273
0
    return 1;
274
0
}
275
276
int ossl_json_flush(OSSL_JSON_ENC *json)
277
0
{
278
0
    return wbuf_flush(&json->wbuf, /*full=*/1);
279
0
}
280
281
int ossl_json_set0_sink(OSSL_JSON_ENC *json, BIO *bio)
282
0
{
283
0
    wbuf_set0_bio(&json->wbuf, bio);
284
0
    return 1;
285
0
}
286
287
int ossl_json_in_error(OSSL_JSON_ENC *json)
288
0
{
289
0
    return json->error;
290
0
}
291
292
/*
293
 * JSON Builder Calls
294
 * ==================
295
 */
296
297
static void json_write_qstring(OSSL_JSON_ENC *json, const char *str);
298
static void json_indent(OSSL_JSON_ENC *json);
299
300
static void json_raise_error(OSSL_JSON_ENC *json)
301
0
{
302
0
    json->error = 1;
303
0
}
304
305
static void json_undefer(OSSL_JSON_ENC *json)
306
0
{
307
0
    if (!json->defer_indent)
308
0
        return;
309
310
0
    json_indent(json);
311
0
}
312
313
static void json_write_char(OSSL_JSON_ENC *json, char ch)
314
0
{
315
0
    if (ossl_json_in_error(json))
316
0
        return;
317
318
0
    json_undefer(json);
319
0
    if (!wbuf_write_char(&json->wbuf, ch))
320
0
        json_raise_error(json);
321
0
}
322
323
static void json_write_str(OSSL_JSON_ENC *json, const char *s)
324
0
{
325
0
    if (ossl_json_in_error(json))
326
0
        return;
327
328
0
    json_undefer(json);
329
0
    if (!wbuf_write_str(&json->wbuf, s))
330
0
        json_raise_error(json);
331
0
}
332
333
static void json_indent(OSSL_JSON_ENC *json)
334
0
{
335
0
    size_t i, depth;
336
337
0
    json->defer_indent = 0;
338
339
0
    if (!in_pretty(json))
340
0
        return;
341
342
0
    json_write_char(json, '\n');
343
344
0
    depth = json->stack_end_byte * 8 + json->stack_end_bit;
345
0
    for (i = 0; i < depth * 4; ++i)
346
0
        json_write_str(json, "    ");
347
0
}
348
349
static int json_pre_item(OSSL_JSON_ENC *json)
350
0
{
351
0
    int s;
352
353
0
    if (ossl_json_in_error(json))
354
0
        return 0;
355
356
0
    switch (json->state) {
357
0
    case STATE_PRE_COMMA:
358
0
        s = json_peek(json);
359
360
0
        if (s == 0) {
361
0
            json_raise_error(json);
362
0
            return 0;
363
0
        }
364
365
0
        if (s == 1) {
366
0
            json_write_char(json, ',');
367
0
            if (ossl_json_in_error(json))
368
0
                return 0;
369
370
0
            json_indent(json);
371
0
        }
372
373
0
        if (s < 0 && in_seq(json))
374
0
            json_write_char(json, '\x1E');
375
376
0
        json->state = STATE_PRE_ITEM;
377
0
        break;
378
379
0
    case STATE_PRE_ITEM:
380
0
        break;
381
382
0
    case STATE_PRE_KEY:
383
0
    default:
384
0
        json_raise_error(json);
385
0
        return 0;
386
0
    }
387
388
0
    return 1;
389
0
}
390
391
static void json_post_item(OSSL_JSON_ENC *json)
392
0
{
393
0
    int s = json_peek(json);
394
395
0
    json->state = STATE_PRE_COMMA;
396
397
0
    if (s < 0 && in_seq(json))
398
0
        json_write_char(json, '\n');
399
0
}
400
401
/*
402
 * Begin a composite structure (object or array).
403
 *
404
 * type: 0=object, 1=array.
405
 */
406
static void composite_begin(OSSL_JSON_ENC *json, int type, char ch)
407
0
{
408
0
    if (!json_pre_item(json)
409
0
        || !json_push(json, type))
410
0
        json_raise_error(json);
411
412
0
    json_write_char(json, ch);
413
0
    json->defer_indent = 1;
414
0
}
415
416
/*
417
 * End a composite structure (object or array).
418
 *
419
 * type: 0=object, 1=array. Errors on mismatch.
420
 */
421
static void composite_end(OSSL_JSON_ENC *json, int type, char ch)
422
0
{
423
0
    int was_defer = json->defer_indent;
424
425
0
    if (ossl_json_in_error(json))
426
0
        return;
427
428
0
    json->defer_indent = 0;
429
430
0
    if (json_peek(json) != type) {
431
0
        json_raise_error(json);
432
0
        return;
433
0
    }
434
435
0
    if (type == 0 && json->state == STATE_PRE_ITEM) {
436
0
        json_raise_error(json);
437
0
        return;
438
0
    }
439
440
0
    if (!json_pop(json)) {
441
0
        json_raise_error(json);
442
0
        return;
443
0
    }
444
445
0
    if (!was_defer)
446
0
        json_indent(json);
447
448
0
    json_write_char(json, ch);
449
0
    json_post_item(json);
450
0
}
451
452
/* Begin a new JSON object. */
453
void ossl_json_object_begin(OSSL_JSON_ENC *json)
454
0
{
455
0
    composite_begin(json, 0, '{');
456
0
    json->state = STATE_PRE_KEY;
457
0
}
458
459
/* End a JSON object. Must be matched with a call to ossl_json_object_begin(). */
460
void ossl_json_object_end(OSSL_JSON_ENC *json)
461
0
{
462
0
    composite_end(json, 0, '}');
463
0
}
464
465
/* Begin a new JSON array. */
466
void ossl_json_array_begin(OSSL_JSON_ENC *json)
467
0
{
468
0
    composite_begin(json, 1, '[');
469
0
    json->state = STATE_PRE_ITEM;
470
0
}
471
472
/* End a JSON array. Must be matched with a call to ossl_json_array_begin(). */
473
void ossl_json_array_end(OSSL_JSON_ENC *json)
474
0
{
475
0
    composite_end(json, 1, ']');
476
0
}
477
478
/*
479
 * Encode a JSON key within an object. Pass a zero-terminated string, which can
480
 * be freed immediately following the call to this function.
481
 */
482
void ossl_json_key(OSSL_JSON_ENC *json, const char *key)
483
0
{
484
0
    if (ossl_json_in_error(json))
485
0
        return;
486
487
0
    if (json_peek(json) != 0) {
488
        /* Not in object */
489
0
        json_raise_error(json);
490
0
        return;
491
0
    }
492
493
0
    if (json->state == STATE_PRE_COMMA) {
494
0
        json_write_char(json, ',');
495
0
        json->state = STATE_PRE_KEY;
496
0
    }
497
498
0
    json_indent(json);
499
0
    if (json->state != STATE_PRE_KEY) {
500
0
        json_raise_error(json);
501
0
        return;
502
0
    }
503
504
0
    json_write_qstring(json, key);
505
0
    if (ossl_json_in_error(json))
506
0
        return;
507
508
0
    json_write_char(json, ':');
509
0
    if (in_pretty(json))
510
0
        json_write_char(json, ' ');
511
512
0
    json->state = STATE_PRE_ITEM;
513
0
}
514
515
/* Encode a JSON 'null' value. */
516
void ossl_json_null(OSSL_JSON_ENC *json)
517
0
{
518
0
    if (!json_pre_item(json))
519
0
        return;
520
521
0
    json_write_str(json, "null");
522
0
    json_post_item(json);
523
0
}
524
525
void ossl_json_bool(OSSL_JSON_ENC *json, int v)
526
0
{
527
0
    if (!json_pre_item(json))
528
0
        return;
529
530
0
    json_write_str(json, v > 0 ? "true" : "false");
531
0
    json_post_item(json);
532
0
}
533
534
0
#define POW_53 (((int64_t)1) << 53)
535
536
/* Encode a JSON integer from a uint64_t. */
537
static void json_u64(OSSL_JSON_ENC *json, uint64_t v, int noquote)
538
0
{
539
0
    char buf[22], *p = buf + sizeof(buf) - 1;
540
0
    int quote = !noquote && in_ijson(json) && v > (uint64_t)(POW_53 - 1);
541
542
0
    if (!json_pre_item(json))
543
0
        return;
544
545
0
    if (quote)
546
0
        json_write_char(json, '"');
547
548
0
    if (v == 0)
549
0
        p = "0";
550
0
    else
551
0
        for (*p = '\0'; v > 0; v /= 10)
552
0
            *--p = '0' + v % 10;
553
554
0
    json_write_str(json, p);
555
556
0
    if (quote)
557
0
        json_write_char(json, '"');
558
559
0
    json_post_item(json);
560
0
}
561
562
void ossl_json_u64(OSSL_JSON_ENC *json, uint64_t v)
563
0
{
564
0
    json_u64(json, v, 0);
565
0
}
566
567
/* Encode a JSON integer from an int64_t. */
568
void ossl_json_i64(OSSL_JSON_ENC *json, int64_t value)
569
0
{
570
0
    uint64_t uv;
571
0
    int quote;
572
573
0
    if (value >= 0) {
574
0
        ossl_json_u64(json, (uint64_t)value);
575
0
        return;
576
0
    }
577
578
0
    if (!json_pre_item(json))
579
0
        return;
580
581
0
    quote = in_ijson(json)
582
0
        && (value > POW_53 - 1 || value < -POW_53 + 1);
583
584
0
    if (quote)
585
0
        json_write_char(json, '"');
586
587
0
    json_write_char(json, '-');
588
589
0
    uv = (value == INT64_MIN)
590
0
        ? ((uint64_t)-(INT64_MIN + 1)) + 1
591
0
        : (uint64_t)-value;
592
0
    json_u64(json, uv, /*noquote=*/1);
593
594
0
    if (quote && !ossl_json_in_error(json))
595
0
        json_write_char(json, '"');
596
0
}
597
598
/* Encode a JSON number from a 64-bit floating point value. */
599
void ossl_json_f64(OSSL_JSON_ENC *json, double value)
600
0
{
601
0
    char buf[32];
602
603
0
    if (!json_pre_item(json))
604
0
        return;
605
606
0
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
607
0
    {
608
0
        int checks = isnan(value);
609
0
# if !defined(OPENSSL_SYS_VMS)
610
0
        checks |= isinf(value);
611
0
# endif
612
613
0
        if (checks) {
614
0
            json_raise_error(json);
615
0
            return;
616
0
        }
617
0
    }
618
0
#endif
619
620
0
    BIO_snprintf(buf, sizeof(buf), "%1.17g", value);
621
0
    json_write_str(json, buf);
622
0
    json_post_item(json);
623
0
}
624
625
/*
626
 * Encode a JSON UTF-8 string from a zero-terminated string. The string passed
627
 * can be freed immediately following the call to this function.
628
 */
629
static ossl_inline int hex_digit(int v)
630
0
{
631
0
    return v >= 10 ? 'a' + (v - 10) : '0' + v;
632
0
}
633
634
static ossl_inline void
635
json_write_qstring_inner(OSSL_JSON_ENC *json, const char *str, size_t str_len,
636
                         int nul_term)
637
0
{
638
0
    char c, *o, obuf[7];
639
0
    unsigned char *u_str;
640
0
    int i;
641
0
    size_t j;
642
643
0
    if (ossl_json_in_error(json))
644
0
        return;
645
646
0
    json_write_char(json, '"');
647
648
0
    for (j = nul_term ? strlen(str) : str_len; j > 0; str++, j--) {
649
0
        c = *str;
650
0
        u_str = (unsigned char*)str;
651
0
        switch (c) {
652
0
        case '\n': o = "\\n"; break;
653
0
        case '\r': o = "\\r"; break;
654
0
        case '\t': o = "\\t"; break;
655
0
        case '\b': o = "\\b"; break;
656
0
        case '\f': o = "\\f"; break;
657
0
        case '"': o = "\\\""; break;
658
0
        case '\\': o = "\\\\"; break;
659
0
        default:
660
            /* valid UTF-8 sequences according to RFC-3629 */
661
0
            if (u_str[0] >= 0xc2 && u_str[0] <= 0xdf && j >= 2
662
0
                    && u_str[1] >= 0x80 && u_str[1] <= 0xbf) {
663
0
                memcpy(obuf, str, 2);
664
0
                obuf[2] = '\0';
665
0
                str++, j--;
666
0
                o = obuf;
667
0
                break;
668
0
            }
669
0
            if (u_str[0] >= 0xe0 && u_str[0] <= 0xef && j >= 3
670
0
                    && u_str[1] >= 0x80 && u_str[1] <= 0xbf
671
0
                    && u_str[2] >= 0x80 && u_str[2] <= 0xbf
672
0
                    && !(u_str[0] == 0xe0 && u_str[1] <= 0x9f)
673
0
                    && !(u_str[0] == 0xed && u_str[1] >= 0xa0)) {
674
0
                memcpy(obuf, str, 3);
675
0
                obuf[3] = '\0';
676
0
                str += 2;
677
0
                j -= 2;
678
0
                o = obuf;
679
0
                break;
680
0
            }
681
0
            if (u_str[0] >= 0xf0 && u_str[0] <= 0xf4 && j >= 4
682
0
                    && u_str[1] >= 0x80 && u_str[1] <= 0xbf
683
0
                    && u_str[2] >= 0x80 && u_str[2] <= 0xbf
684
0
                    && u_str[3] >= 0x80 && u_str[3] <= 0xbf
685
0
                    && !(u_str[0] == 0xf0 && u_str[1] <= 0x8f)
686
0
                    && !(u_str[0] == 0xf4 && u_str[1] >= 0x90)) {
687
0
                memcpy(obuf, str, 4);
688
0
                obuf[4] = '\0';
689
0
                str += 3;
690
0
                j -= 3;
691
0
                o = obuf;
692
0
                break;
693
0
            }
694
0
            if (u_str[0] < 0x20 || u_str[0] >= 0x7f) {
695
0
                obuf[0] = '\\';
696
0
                obuf[1] = 'u';
697
0
                for (i = 0; i < 4; ++i)
698
0
                    obuf[2 + i] = hex_digit((u_str[0] >> ((3 - i) * 4)) & 0x0F);
699
0
                obuf[6] = '\0';
700
0
                o = obuf;
701
0
            } else {
702
0
                json_write_char(json, c);
703
0
                continue;
704
0
            }
705
0
            break;
706
0
        }
707
708
0
        json_write_str(json, o);
709
0
    }
710
711
0
    json_write_char(json, '"');
712
0
}
713
714
static void
715
json_write_qstring(OSSL_JSON_ENC *json, const char *str)
716
0
{
717
0
    json_write_qstring_inner(json, str, 0, 1);
718
0
}
719
720
static void
721
json_write_qstring_len(OSSL_JSON_ENC *json, const char *str, size_t str_len)
722
0
{
723
0
    json_write_qstring_inner(json, str, str_len, 0);
724
0
}
725
726
void ossl_json_str(OSSL_JSON_ENC *json, const char *str)
727
0
{
728
0
    if (!json_pre_item(json))
729
0
        return;
730
731
0
    json_write_qstring(json, str);
732
0
    json_post_item(json);
733
0
}
734
735
void ossl_json_str_len(OSSL_JSON_ENC *json, const char *str, size_t str_len)
736
0
{
737
0
    if (!json_pre_item(json))
738
0
        return;
739
740
0
    json_write_qstring_len(json, str, str_len);
741
0
    json_post_item(json);
742
0
}
743
744
/*
745
 * Encode binary data as a lowercase hex string. data_len is the data length in
746
 * bytes.
747
 */
748
void ossl_json_str_hex(OSSL_JSON_ENC *json, const void *data, size_t data_len)
749
0
{
750
0
    const unsigned char *b = data, *end = b + data_len;
751
0
    unsigned char c;
752
753
0
    if (!json_pre_item(json))
754
0
        return;
755
756
0
    json_write_char(json, '"');
757
758
0
    for (; b < end; ++b) {
759
0
        c = *b;
760
0
        json_write_char(json, hex_digit(c >> 4));
761
0
        json_write_char(json, hex_digit(c & 0x0F));
762
0
    }
763
764
0
    json_write_char(json, '"');
765
0
    json_post_item(json);
766
0
}