Coverage Report

Created: 2024-01-26 01:52

/work/toxcore/bin_unpack.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2022 The TokTok team.
3
 */
4
5
#include "bin_unpack.h"
6
7
#include <assert.h>
8
#include <stdlib.h>
9
#include <string.h>
10
11
#include "../third_party/cmp/cmp.h"
12
#include "ccompat.h"
13
14
struct Bin_Unpack {
15
    const uint8_t *bytes;
16
    uint32_t bytes_size;
17
    cmp_ctx_t ctx;
18
};
19
20
non_null()
21
static bool buf_reader(cmp_ctx_t *ctx, void *data, size_t limit)
22
162k
{
23
162k
    Bin_Unpack *reader = (Bin_Unpack *)ctx->buf;
24
162k
    assert(reader != nullptr && reader->bytes != nullptr);
25
162k
    if (limit > reader->bytes_size) {
26
5.62k
        return false;
27
5.62k
    }
28
156k
    memcpy(data, reader->bytes, limit);
29
156k
    reader->bytes += limit;
30
156k
    reader->bytes_size -= limit;
31
156k
    return true;
32
162k
}
33
34
non_null()
35
static bool buf_skipper(cmp_ctx_t *ctx, size_t count)
36
0
{
37
0
    Bin_Unpack *reader = (Bin_Unpack *)ctx->buf;
38
0
    assert(reader != nullptr && reader->bytes != nullptr);
39
0
    if (count > reader->bytes_size) {
40
0
        return false;
41
0
    }
42
0
    reader->bytes += count;
43
0
    reader->bytes_size -= count;
44
0
    return true;
45
0
}
46
47
non_null()
48
static size_t null_writer(cmp_ctx_t *ctx, const void *data, size_t count)
49
0
{
50
0
    assert(count == 0);
51
0
    return 0;
52
0
}
53
54
non_null()
55
static void bin_unpack_init(Bin_Unpack *bu, const uint8_t *buf, uint32_t buf_size)
56
15.2k
{
57
15.2k
    bu->bytes = buf;
58
15.2k
    bu->bytes_size = buf_size;
59
15.2k
    cmp_init(&bu->ctx, bu, buf_reader, buf_skipper, null_writer);
60
15.2k
}
61
62
bool bin_unpack_obj(bin_unpack_cb *callback, void *obj, const uint8_t *buf, uint32_t buf_size)
63
15.2k
{
64
15.2k
    Bin_Unpack bu;
65
15.2k
    bin_unpack_init(&bu, buf, buf_size);
66
15.2k
    return callback(obj, &bu);
67
15.2k
}
68
69
bool bin_unpack_array(Bin_Unpack *bu, uint32_t *size)
70
15.2k
{
71
15.2k
    return cmp_read_array(&bu->ctx, size) && *size <= bu->bytes_size;
72
15.2k
}
73
74
bool bin_unpack_array_fixed(Bin_Unpack *bu, uint32_t required_size, uint32_t *actual_size)
75
32.6k
{
76
32.6k
    uint32_t size = 0;
77
32.6k
    const bool success = cmp_read_array(&bu->ctx, &size) && size == required_size;
78
32.6k
    if (actual_size != nullptr) {
79
14.5k
        *actual_size = size;
80
14.5k
    }
81
32.6k
    return success;
82
32.6k
}
83
84
bool bin_unpack_bool(Bin_Unpack *bu, bool *val)
85
11.7k
{
86
11.7k
    return cmp_read_bool(&bu->ctx, val);
87
11.7k
}
88
89
bool bin_unpack_u08(Bin_Unpack *bu, uint8_t *val)
90
16.5k
{
91
16.5k
    return cmp_read_uchar(&bu->ctx, val);
92
16.5k
}
93
94
bool bin_unpack_u16(Bin_Unpack *bu, uint16_t *val)
95
30.5k
{
96
30.5k
    return cmp_read_ushort(&bu->ctx, val);
97
30.5k
}
98
99
bool bin_unpack_u32(Bin_Unpack *bu, uint32_t *val)
100
20.7k
{
101
20.7k
    return cmp_read_uint(&bu->ctx, val);
102
20.7k
}
103
104
bool bin_unpack_u64(Bin_Unpack *bu, uint64_t *val)
105
148
{
106
148
    return cmp_read_ulong(&bu->ctx, val);
107
148
}
108
109
bool bin_unpack_nil(Bin_Unpack *bu)
110
94
{
111
94
    return cmp_read_nil(&bu->ctx);
112
94
}
113
114
bool bin_unpack_bin(Bin_Unpack *bu, uint8_t **data_ptr, uint32_t *data_length_ptr)
115
487
{
116
487
    uint32_t bin_size;
117
487
    if (!bin_unpack_bin_size(bu, &bin_size) || bin_size > bu->bytes_size) {
118
        // There aren't as many bytes as this bin claims to want to allocate.
119
57
        return false;
120
57
    }
121
430
    uint8_t *const data = (uint8_t *)malloc(bin_size);
122
123
430
    if (!bin_unpack_bin_b(bu, data, bin_size)) {
124
0
        free(data);
125
0
        return false;
126
0
    }
127
128
430
    *data_ptr = data;
129
430
    *data_length_ptr = bin_size;
130
430
    return true;
131
430
}
132
133
bool bin_unpack_bin_max(Bin_Unpack *bu, uint8_t *data, uint16_t *data_length_ptr, uint16_t max_data_length)
134
1.42k
{
135
1.42k
    uint32_t bin_size;
136
1.42k
    if (!bin_unpack_bin_size(bu, &bin_size) || bin_size > max_data_length) {
137
85
        return false;
138
85
    }
139
140
1.34k
    *data_length_ptr = bin_size;
141
142
1.34k
    return bin_unpack_bin_b(bu, data, bin_size);
143
1.42k
}
144
145
bool bin_unpack_bin_fixed(Bin_Unpack *bu, uint8_t *data, uint32_t data_length)
146
5.32k
{
147
5.32k
    uint32_t bin_size;
148
5.32k
    if (!bin_unpack_bin_size(bu, &bin_size) || bin_size != data_length) {
149
1.64k
        return false;
150
1.64k
    }
151
152
3.68k
    return bin_unpack_bin_b(bu, data, bin_size);
153
5.32k
}
154
155
bool bin_unpack_bin_size(Bin_Unpack *bu, uint32_t *size)
156
7.23k
{
157
7.23k
    return cmp_read_bin_size(&bu->ctx, size);
158
7.23k
}
159
160
bool bin_unpack_u08_b(Bin_Unpack *bu, uint8_t *val)
161
18
{
162
18
    return bin_unpack_bin_b(bu, val, 1);
163
18
}
164
165
bool bin_unpack_u16_b(Bin_Unpack *bu, uint16_t *val)
166
9
{
167
9
    uint8_t hi = 0;
168
9
    uint8_t lo = 0;
169
9
    if (!(bin_unpack_u08_b(bu, &hi)
170
9
          && bin_unpack_u08_b(bu, &lo))) {
171
0
        return false;
172
0
    }
173
9
    *val = ((uint16_t)hi << 8) | lo;
174
9
    return true;
175
9
}
176
177
bool bin_unpack_u32_b(Bin_Unpack *bu, uint32_t *val)
178
4
{
179
4
    uint16_t hi = 0;
180
4
    uint16_t lo = 0;
181
4
    if (!(bin_unpack_u16_b(bu, &hi)
182
4
          && bin_unpack_u16_b(bu, &lo))) {
183
0
        return false;
184
0
    }
185
4
    *val = ((uint32_t)hi << 16) | lo;
186
4
    return true;
187
4
}
188
189
bool bin_unpack_u64_b(Bin_Unpack *bu, uint64_t *val)
190
2
{
191
2
    uint32_t hi = 0;
192
2
    uint32_t lo = 0;
193
2
    if (!(bin_unpack_u32_b(bu, &hi)
194
2
          && bin_unpack_u32_b(bu, &lo))) {
195
0
        return false;
196
0
    }
197
2
    *val = ((uint64_t)hi << 32) | lo;
198
2
    return true;
199
2
}
200
201
bool bin_unpack_bin_b(Bin_Unpack *bu, uint8_t *data, uint32_t length)
202
5.47k
{
203
5.47k
    return bu->ctx.read(&bu->ctx, data, length);
204
5.47k
}