Coverage Report

Created: 2026-10-24 08:16

/work/toxcore/bin_pack.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2022-2026 The TokTok team.
3
 */
4
5
#include "bin_pack.h"
6
7
#include <assert.h>
8
#include <string.h>
9
10
#include "../third_party/cmp/cmp.h"
11
#include "attributes.h"
12
#include "ccompat.h"
13
#include "logger.h"
14
15
struct Bin_Pack {
16
    uint8_t *_Nullable bytes;
17
    uint32_t bytes_size;
18
    uint32_t bytes_pos;
19
    cmp_ctx_t ctx;
20
};
21
22
static bool null_reader(cmp_ctx_t *_Nonnull ctx, void *_Nullable data, size_t limit)
23
0
{
24
0
    assert(limit == 0);
25
0
    return false;
26
0
}
27
28
static bool null_skipper(cmp_ctx_t *_Nonnull ctx, size_t count)
29
0
{
30
0
    assert(count == 0);
31
0
    return false;
32
0
}
33
34
static size_t buf_writer(cmp_ctx_t *_Nonnull ctx, const void *_Nullable data, size_t count)
35
5.04M
{
36
5.04M
    const uint8_t *const bytes = (const uint8_t *)data;
37
38
5.04M
    if (count == 0) {
39
1
        return 0;
40
1
    }
41
42
5.04M
    if (bytes == nullptr) {
43
0
        return 0;
44
0
    }
45
5.04M
    Bin_Pack *const bp = (Bin_Pack *)ctx->buf;
46
5.04M
    assert(bp != nullptr);
47
5.04M
    const uint32_t new_pos = bp->bytes_pos + count;
48
5.04M
    if (new_pos < bp->bytes_pos) {
49
        // 32 bit overflow.
50
0
        return 0;
51
0
    }
52
5.04M
    if (bp->bytes != nullptr) {
53
2.51M
        if (new_pos > bp->bytes_size) {
54
            // Buffer too small.
55
1
            return 0;
56
1
        }
57
2.51M
        memcpy(&bp->bytes[bp->bytes_pos], bytes, count);
58
2.51M
    }
59
5.04M
    bp->bytes_pos += count;
60
5.04M
    return count;
61
5.04M
}
62
63
static void bin_pack_init(Bin_Pack *_Nonnull bp, uint8_t *_Nullable buf, uint32_t buf_size)
64
630k
{
65
630k
    bp->bytes = buf;
66
630k
    bp->bytes_size = buf_size;
67
630k
    bp->bytes_pos = 0;
68
630k
    cmp_init(&bp->ctx, bp, null_reader, null_skipper, buf_writer);
69
630k
}
70
71
uint32_t bin_pack_obj_size(bin_pack_cb *callback, const void *obj, const Logger *logger)
72
82.8k
{
73
82.8k
    Bin_Pack bp;
74
82.8k
    bin_pack_init(&bp, nullptr, 0);
75
82.8k
    if (!callback(obj, logger, &bp)) {
76
0
        return UINT32_MAX;
77
0
    }
78
82.8k
    return bp.bytes_pos;
79
82.8k
}
80
81
bool bin_pack_obj(bin_pack_cb *callback, const void *obj, const Logger *logger, uint8_t *buf, uint32_t buf_size)
82
81.2k
{
83
81.2k
    Bin_Pack bp;
84
81.2k
    bin_pack_init(&bp, buf, buf_size);
85
81.2k
    return callback(obj, logger, &bp);
86
81.2k
}
87
88
uint32_t bin_pack_obj_array_b_size(bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger)
89
233k
{
90
233k
    Bin_Pack bp;
91
233k
    bin_pack_init(&bp, nullptr, 0);
92
233k
    if (arr == nullptr) {
93
0
        assert(arr_size == 0);
94
0
    }
95
671k
    for (uint32_t i = 0; i < arr_size; ++i) {
96
438k
        if (!callback(arr, i, logger, &bp)) {
97
188
            return UINT32_MAX;
98
188
        }
99
438k
    }
100
232k
    return bp.bytes_pos;
101
233k
}
102
103
bool bin_pack_obj_array_b(bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger, uint8_t *buf, uint32_t buf_size)
104
233k
{
105
233k
    Bin_Pack bp;
106
233k
    bin_pack_init(&bp, buf, buf_size);
107
233k
    if (arr == nullptr) {
108
0
        assert(arr_size == 0);
109
0
    }
110
671k
    for (uint32_t i = 0; i < arr_size; ++i) {
111
438k
        if (!callback(arr, i, logger, &bp)) {
112
188
            return false;
113
188
        }
114
438k
    }
115
232k
    return true;
116
233k
}
117
118
bool bin_pack_obj_array(Bin_Pack *bp, bin_pack_array_cb *callback, const void *arr, uint32_t arr_size, const Logger *logger)
119
3.17k
{
120
3.17k
    if (arr == nullptr) {
121
2.66k
        assert(arr_size == 0);
122
2.66k
        return bin_pack_array(bp, 0);
123
2.66k
    }
124
125
506
    if (!bin_pack_array(bp, arr_size)) {
126
0
        return false;
127
0
    }
128
129
2.35k
    for (uint32_t i = 0; i < arr_size; ++i) {
130
1.85k
        if (!callback(arr, i, logger, bp)) {
131
0
            return false;
132
0
        }
133
1.85k
    }
134
135
506
    return true;
136
506
}
137
138
bool bin_pack_array(Bin_Pack *bp, uint32_t size)
139
10.7k
{
140
10.7k
    return cmp_write_array(&bp->ctx, size);
141
10.7k
}
142
143
bool bin_pack_bool(Bin_Pack *bp, bool val)
144
304
{
145
304
    return cmp_write_bool(&bp->ctx, val);
146
304
}
147
148
bool bin_pack_u08(Bin_Pack *bp, uint8_t val)
149
1.04k
{
150
1.04k
    return cmp_write_uinteger(&bp->ctx, val);
151
1.04k
}
152
153
bool bin_pack_u16(Bin_Pack *bp, uint16_t val)
154
2.43k
{
155
2.43k
    return cmp_write_uinteger(&bp->ctx, val);
156
2.43k
}
157
158
bool bin_pack_u32(Bin_Pack *bp, uint32_t val)
159
5.41k
{
160
5.41k
    return cmp_write_uinteger(&bp->ctx, val);
161
5.41k
}
162
163
bool bin_pack_u64(Bin_Pack *bp, uint64_t val)
164
168
{
165
168
    return cmp_write_uinteger(&bp->ctx, val);
166
168
}
167
168
bool bin_pack_bin(Bin_Pack *bp, const uint8_t *data, uint32_t length)
169
4.72k
{
170
4.72k
    if (length == 0) {
171
828
        return cmp_write_bin_marker(&bp->ctx, 0);
172
828
    }
173
174
3.89k
    if (data == nullptr) {
175
1
        return false;
176
1
    }
177
178
3.89k
    return cmp_write_bin(&bp->ctx, data, length);
179
3.89k
}
180
181
bool bin_pack_str(Bin_Pack *bp, const char *data, uint32_t length)
182
249
{
183
249
    if (length == 0) {
184
5
        return cmp_write_str_marker(&bp->ctx, 0);
185
5
    }
186
187
244
    if (data == nullptr) {
188
1
        return false;
189
1
    }
190
191
243
    return cmp_write_str(&bp->ctx, data, length);
192
244
}
193
194
bool bin_pack_nil(Bin_Pack *bp)
195
76
{
196
76
    return cmp_write_nil(&bp->ctx);
197
76
}
198
199
bool bin_pack_bin_marker(Bin_Pack *bp, uint32_t size)
200
2
{
201
2
    return cmp_write_bin_marker(&bp->ctx, size);
202
2
}
203
204
bool bin_pack_u08_b(Bin_Pack *bp, uint8_t val)
205
3.10M
{
206
3.10M
    return bp->ctx.write(&bp->ctx, &val, 1) == 1;
207
3.10M
}
208
209
bool bin_pack_u16_b(Bin_Pack *bp, uint16_t val)
210
1.03M
{
211
1.03M
    return bin_pack_u08_b(bp, (val >> 8) & 0xff)
212
1.03M
           && bin_pack_u08_b(bp, val & 0xff);
213
1.03M
}
214
215
bool bin_pack_u32_b(Bin_Pack *bp, uint32_t val)
216
6
{
217
6
    return bin_pack_u16_b(bp, (val >> 16) & 0xffff)
218
6
           && bin_pack_u16_b(bp, val & 0xffff);
219
6
}
220
221
bool bin_pack_u64_b(Bin_Pack *bp, uint64_t val)
222
3
{
223
3
    return bin_pack_u32_b(bp, (val >> 32) & 0xffffffff)
224
3
           && bin_pack_u32_b(bp, val & 0xffffffff);
225
3
}
226
227
bool bin_pack_bin_b(Bin_Pack *bp, const uint8_t *data, uint32_t length)
228
1.91M
{
229
1.91M
    if (length > 0 && data == nullptr) {
230
1
        return false;
231
1
    }
232
233
1.91M
    return bp->ctx.write(&bp->ctx, data, length) == length;
234
1.91M
}