Coverage Report

Created: 2026-03-30 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/wscbor_enc.c
Line
Count
Source
1
/** @file
2
 * Wireshark CBOR item encoding API.
3
 * References:
4
 *     RFC 8949: https://tools.ietf.org/html/rfc8949
5
 *
6
 * Copyright 2017, Malisa Vucinic <malishav@gmail.com>
7
 * Copyright 2019-2025, Brian Sipos <brian.sipos@gmail.com>
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: LGPL-2.1-or-later
14
 */
15
16
// Use typedefs from wscbor header
17
#include <epan/wscbor.h>
18
#include "wscbor_enc.h"
19
20
/** Encode a CBOR head using the same strategy as QCBOR double loop.
21
 */
22
0
static void wscbor_enc_head(GByteArray *buf, uint8_t type_major, uint64_t arg) {
23
0
    const uint8_t maj_mask = type_major << 5;
24
25
0
    if (arg <= 0x17 ) {
26
0
        const uint8_t tmp[1] = { maj_mask | (uint8_t)arg };
27
0
        g_byte_array_append(buf, tmp, sizeof(tmp));
28
0
    }
29
0
    else {
30
0
        static const unsigned inc_size[] = {1, 1, 2, 4};
31
        // buffer maximum possible head size and right-align
32
0
        uint8_t tmp[9];
33
0
        uint8_t *curs = tmp + 9;
34
0
        unsigned used = 0;
35
36
0
        uint8_t type_minor = 0x17;
37
        // Each inner loop trims the arg by one byte and its size is 8 bytes
38
0
        for (int ix = 0; arg; ++ix) {
39
            // write entire increment at each step
40
0
            const unsigned next = inc_size[ix];
41
0
            for (unsigned jx = 0; jx < next; ++jx) {
42
0
                *--curs = (uint8_t)(arg & 0xFF);
43
0
                arg >>= 8;
44
0
                ++used;
45
0
            }
46
0
            ++type_minor;
47
0
        }
48
49
        // leading octet
50
0
        *--curs = maj_mask | type_minor;
51
0
        ++used;
52
53
0
        g_byte_array_append(buf, curs, used);
54
0
    }
55
0
}
56
57
0
void wscbor_enc_undefined(GByteArray *buf) {
58
0
    wscbor_enc_head(buf, CBOR_TYPE_FLOAT_CTRL, CBOR_CTRL_UNDEF);
59
0
}
60
61
0
void wscbor_enc_null(GByteArray *buf) {
62
0
    wscbor_enc_head(buf, CBOR_TYPE_FLOAT_CTRL, CBOR_CTRL_NULL);
63
0
}
64
65
0
void wscbor_enc_boolean(GByteArray *buf, bool value) {
66
0
    wscbor_enc_head(buf, CBOR_TYPE_FLOAT_CTRL, value ? CBOR_CTRL_TRUE : CBOR_CTRL_FALSE);
67
0
}
68
69
0
void wscbor_enc_uint64(GByteArray *buf, uint64_t value) {
70
0
    wscbor_enc_head(buf, CBOR_TYPE_UINT, value);
71
0
}
72
73
0
void wscbor_enc_int64(GByteArray *buf, int64_t value) {
74
0
    if (value >= 0) {
75
0
        uint64_t arg = value;
76
0
        wscbor_enc_head(buf, CBOR_TYPE_UINT, arg);
77
0
    }
78
0
    else {
79
0
        uint64_t arg = -1 - value;
80
0
        wscbor_enc_head(buf, CBOR_TYPE_NEGINT, arg);
81
0
    }
82
0
}
83
84
0
void wscbor_enc_bstr(GByteArray *buf, const uint8_t *ptr, size_t len) {
85
0
    wscbor_enc_head(buf, CBOR_TYPE_BYTESTRING, len);
86
0
    if (len && (len < UINT_MAX)) {
87
0
        g_byte_array_append(buf, ptr, (unsigned)len);
88
0
    }
89
0
}
90
91
0
void wscbor_enc_bstr_bytearray(GByteArray *buf, GByteArray *src) {
92
0
    size_t len = 0;
93
0
    uint8_t *ptr = g_byte_array_steal(src, &len);
94
0
    wscbor_enc_bstr(buf, ptr, len);
95
0
    g_free(ptr);
96
0
}
97
98
0
void wscbor_enc_tstr(GByteArray *buf, const char *ptr) {
99
    // exclude terminating null from CBOR
100
0
    const size_t len = ptr ? strlen(ptr) : 0;
101
0
    wscbor_enc_head(buf, CBOR_TYPE_STRING, len);
102
0
    if (len && (len < UINT_MAX)) {
103
0
        g_byte_array_append(buf, (const uint8_t*)ptr, (unsigned)len);
104
0
    }
105
0
}
106
107
0
void wscbor_enc_array_head(GByteArray *buf, size_t len) {
108
0
    wscbor_enc_head(buf, CBOR_TYPE_ARRAY, len);
109
0
}
110
111
0
void wscbor_enc_map_head(GByteArray *buf, size_t len) {
112
0
    wscbor_enc_head(buf, CBOR_TYPE_MAP, len);
113
0
}