Coverage Report

Created: 2025-12-31 07:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/demux/xiph.h
Line
Count
Source
1
/*****************************************************************************
2
 * xiph.h: Xiph helpers
3
 *****************************************************************************
4
 * Copyright (C) 2010 Laurent Aimar
5
 *
6
 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program; if not, write to the Free Software Foundation,
20
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21
 *****************************************************************************/
22
23
#include <assert.h>
24
#include <limits.h>
25
249k
#define XIPH_MAX_HEADER_COUNT (256)
26
27
/* Temp ffmpeg vorbis format */
28
static inline bool xiph_IsLavcFormat(const void *extra, size_t i_extra,
29
                                     vlc_fourcc_t i_codec)
30
0
{
31
0
    switch(i_codec)
32
0
    {
33
0
        case VLC_CODEC_VORBIS:
34
0
            return i_extra >= 6 && GetWBE(extra) == 30;
35
0
        case VLC_CODEC_THEORA:
36
0
            return i_extra >= 6 && GetWBE(extra) == 42;
37
0
        default:
38
0
            return false;
39
0
    }
40
0
}
Unexecuted instantiation: essetup.c:xiph_IsLavcFormat
Unexecuted instantiation: ogg.c:xiph_IsLavcFormat
Unexecuted instantiation: matroska_segment_parse.cpp:xiph_IsLavcFormat(void const*, unsigned long, unsigned int)
41
42
static inline unsigned xiph_CountLavcHeaders(const void *p_extra, size_t i_extra)
43
0
{
44
0
    const uint8_t *p = (const uint8_t*) p_extra;
45
0
    const uint8_t *p_end = &p[i_extra];
46
0
    /* Check headers count */
47
0
    for (int i=0; i<3; i++)
48
0
    {
49
0
        if(p_end - p < 2)
50
0
            return 0;
51
0
        uint16_t i_size = GetWBE(p);
52
0
        if(&p[2U + i_size] > p_end)
53
0
            return 0;
54
0
        p += 2 + i_size;
55
0
    }
56
0
    return 3;
57
0
}
Unexecuted instantiation: essetup.c:xiph_CountLavcHeaders
Unexecuted instantiation: ogg.c:xiph_CountLavcHeaders
Unexecuted instantiation: matroska_segment_parse.cpp:xiph_CountLavcHeaders(void const*, unsigned long)
58
59
static inline unsigned xiph_CountHeaders(const void *p_extra, size_t i_extra)
60
76.9k
{
61
76.9k
    const uint8_t *p = (const uint8_t*) p_extra;
62
76.9k
    if (!i_extra)
63
0
        return 0;
64
    /* First byte is headers count */
65
76.9k
    if(1U + *p > i_extra)
66
0
        return 0;
67
76.9k
    return *p + 1;
68
76.9k
}
Unexecuted instantiation: essetup.c:xiph_CountHeaders
ogg.c:xiph_CountHeaders
Line
Count
Source
60
76.9k
{
61
76.9k
    const uint8_t *p = (const uint8_t*) p_extra;
62
76.9k
    if (!i_extra)
63
0
        return 0;
64
    /* First byte is headers count */
65
76.9k
    if(1U + *p > i_extra)
66
0
        return 0;
67
76.9k
    return *p + 1;
68
76.9k
}
Unexecuted instantiation: matroska_segment_parse.cpp:xiph_CountHeaders(void const*, unsigned long)
69
70
static inline unsigned xiph_CountUnknownHeaders(const void *p_extra, unsigned i_extra,
71
                                                vlc_fourcc_t i_codec)
72
0
{
73
0
    if (xiph_IsLavcFormat(p_extra, i_extra, i_codec))
74
0
        return xiph_CountLavcHeaders(p_extra, i_extra);
75
0
    else
76
0
        return xiph_CountHeaders(p_extra, i_extra);
77
0
}
Unexecuted instantiation: essetup.c:xiph_CountUnknownHeaders
Unexecuted instantiation: ogg.c:xiph_CountUnknownHeaders
Unexecuted instantiation: matroska_segment_parse.cpp:xiph_CountUnknownHeaders(void const*, unsigned int, unsigned int)
78
79
static inline int xiph_SplitLavcHeaders(size_t packet_size[],
80
                                        const void *packet[], size_t *packet_count,
81
                                        size_t i_extra, const void *p_extra)
82
0
{
83
0
    const uint8_t *current = (const uint8_t *)p_extra;
84
0
    const uint8_t *end = &current[i_extra];
85
0
    if (i_extra < 2)
86
0
        return VLC_EGENERIC;
87
0
    /* Parse the packet count and their sizes */
88
0
    const unsigned count = xiph_CountLavcHeaders(current, i_extra);
89
0
    if(count == 0)
90
0
        return VLC_EGENERIC;
91
0
    if (packet_count)
92
0
        *packet_count = count;
93
0
    /* count is trusted here (xiph_CountHeaders) */
94
0
    for (unsigned i=0; i < count; i++)
95
0
    {
96
0
        /* each payload is prefixed by word size */
97
0
        packet_size[i] = GetWBE(current);
98
0
        if(&current[2U + packet_size[i]] > end)
99
0
            return VLC_EGENERIC;
100
0
        packet[i] = current + 2;
101
0
        current += packet_size[i] + 2;
102
0
    }
103
0
    return VLC_SUCCESS;
104
0
}
Unexecuted instantiation: essetup.c:xiph_SplitLavcHeaders
Unexecuted instantiation: ogg.c:xiph_SplitLavcHeaders
Unexecuted instantiation: matroska_segment_parse.cpp:xiph_SplitLavcHeaders(unsigned long*, void const**, unsigned long*, unsigned long, void const*)
105
106
static inline int xiph_SplitHeaders(size_t packet_size[],
107
                                    const void *packet[], size_t *packet_count,
108
                                    size_t i_extra, const void *p_extra)
109
77.8k
{
110
77.8k
    const uint8_t *current = (const uint8_t *)p_extra;
111
77.8k
    const uint8_t *end = &current[i_extra];
112
77.8k
    if (i_extra < 1)
113
858
        return VLC_EGENERIC;
114
115
    /* Parse the packet count and their sizes */
116
76.9k
    const unsigned count = xiph_CountHeaders(current, i_extra);
117
76.9k
    if(count == 0)
118
0
        return VLC_EGENERIC;
119
120
76.9k
    if (packet_count)
121
76.9k
        *packet_count = count;
122
123
    /* - 1 byte (N-1) packets
124
     * - N-1 variable length payload sizes
125
     * - N-1 payloads
126
     * - Nth packet (remaining)  */
127
128
    /* skip count byte header */
129
76.9k
    ++current;
130
    /* read sizes for N-1 packets */
131
76.9k
    unsigned total_payload_minus_last = 0;
132
6.02M
    for (unsigned i = 0; i < count - 1; i++)
133
5.95M
    {
134
5.95M
        packet_size[i] = 0;
135
6.06M
        for (;;) {
136
6.06M
            if (current >= end)
137
0
                return VLC_EGENERIC;
138
6.06M
            packet_size[i] += *current;
139
6.06M
            if (*current++ != 255)
140
5.95M
                break;
141
6.06M
        }
142
5.95M
        if(UINT_MAX - total_payload_minus_last < packet_size[i])
143
0
            return VLC_EGENERIC;
144
5.95M
        total_payload_minus_last += packet_size[i];
145
5.95M
    }
146
76.9k
    if(current + total_payload_minus_last > end)
147
0
        return VLC_EGENERIC;
148
    /* set pointers for N-1 packets */
149
6.02M
    for (unsigned i = 0; i < count - 1; i++)
150
5.95M
    {
151
5.95M
        packet[i] = current;
152
5.95M
        current += packet_size[i];
153
5.95M
    }
154
    /* Last packet is remaining size */
155
76.9k
    packet_size[count - 1] = end - current;
156
76.9k
    packet[count - 1] = current;
157
158
76.9k
    return VLC_SUCCESS;
159
76.9k
}
Unexecuted instantiation: essetup.c:xiph_SplitHeaders
ogg.c:xiph_SplitHeaders
Line
Count
Source
109
77.8k
{
110
77.8k
    const uint8_t *current = (const uint8_t *)p_extra;
111
77.8k
    const uint8_t *end = &current[i_extra];
112
77.8k
    if (i_extra < 1)
113
858
        return VLC_EGENERIC;
114
115
    /* Parse the packet count and their sizes */
116
76.9k
    const unsigned count = xiph_CountHeaders(current, i_extra);
117
76.9k
    if(count == 0)
118
0
        return VLC_EGENERIC;
119
120
76.9k
    if (packet_count)
121
76.9k
        *packet_count = count;
122
123
    /* - 1 byte (N-1) packets
124
     * - N-1 variable length payload sizes
125
     * - N-1 payloads
126
     * - Nth packet (remaining)  */
127
128
    /* skip count byte header */
129
76.9k
    ++current;
130
    /* read sizes for N-1 packets */
131
76.9k
    unsigned total_payload_minus_last = 0;
132
6.02M
    for (unsigned i = 0; i < count - 1; i++)
133
5.95M
    {
134
5.95M
        packet_size[i] = 0;
135
6.06M
        for (;;) {
136
6.06M
            if (current >= end)
137
0
                return VLC_EGENERIC;
138
6.06M
            packet_size[i] += *current;
139
6.06M
            if (*current++ != 255)
140
5.95M
                break;
141
6.06M
        }
142
5.95M
        if(UINT_MAX - total_payload_minus_last < packet_size[i])
143
0
            return VLC_EGENERIC;
144
5.95M
        total_payload_minus_last += packet_size[i];
145
5.95M
    }
146
76.9k
    if(current + total_payload_minus_last > end)
147
0
        return VLC_EGENERIC;
148
    /* set pointers for N-1 packets */
149
6.02M
    for (unsigned i = 0; i < count - 1; i++)
150
5.95M
    {
151
5.95M
        packet[i] = current;
152
5.95M
        current += packet_size[i];
153
5.95M
    }
154
    /* Last packet is remaining size */
155
76.9k
    packet_size[count - 1] = end - current;
156
76.9k
    packet[count - 1] = current;
157
158
76.9k
    return VLC_SUCCESS;
159
76.9k
}
Unexecuted instantiation: matroska_segment_parse.cpp:xiph_SplitHeaders(unsigned long*, void const**, unsigned long*, unsigned long, void const*)
160
161
static inline int xiph_PackHeaders(size_t *extra_size, void **extra,
162
                                   size_t packet_size[],
163
                                   const void *const packet[],
164
                                   size_t packet_count)
165
124k
{
166
124k
    if (packet_count <= 0 || packet_count > XIPH_MAX_HEADER_COUNT)
167
0
        return VLC_EGENERIC;
168
169
    /* Compute the size needed for the whole extra data */
170
124k
    size_t payload_size = 0;
171
124k
    size_t header_size = 1;
172
6.19M
    for (size_t i = 0; i < packet_count; i++) {
173
6.07M
        payload_size += packet_size[i];
174
6.07M
        if (i < packet_count - 1)
175
5.94M
            header_size += 1 + packet_size[i] / 255;
176
6.07M
    }
177
178
    /* */
179
124k
    *extra_size = header_size + payload_size;
180
124k
    *extra = malloc(*extra_size);
181
124k
    if (*extra == NULL)
182
0
        return VLC_ENOMEM;
183
184
    /* Write the header */
185
124k
    uint8_t *current = (uint8_t*)*extra;
186
124k
    *current++ = packet_count - 1;
187
6.07M
    for (size_t i = 0; i < packet_count - 1; i++) {
188
5.94M
        size_t t = packet_size[i];
189
6.05M
        for (;;) {
190
6.05M
            if (t >= 255) {
191
112k
                *current++ = 255;
192
112k
                t -= 255;
193
5.94M
            } else {
194
5.94M
                *current++ = t;
195
5.94M
                break;
196
5.94M
            }
197
6.05M
        }
198
5.94M
    }
199
200
    /* Copy the payloads */
201
6.19M
    for (size_t i = 0; i < packet_count; i++) {
202
6.07M
        if (packet_size[i] > 0) {
203
6.04M
            memcpy(current, packet[i], packet_size[i]);
204
6.04M
            current += packet_size[i];
205
6.04M
        }
206
6.07M
    }
207
124k
    assert(current == (uint8_t*)*extra + *extra_size);
208
124k
    return VLC_SUCCESS;
209
124k
}
Unexecuted instantiation: essetup.c:xiph_PackHeaders
ogg.c:xiph_PackHeaders
Line
Count
Source
165
124k
{
166
124k
    if (packet_count <= 0 || packet_count > XIPH_MAX_HEADER_COUNT)
167
0
        return VLC_EGENERIC;
168
169
    /* Compute the size needed for the whole extra data */
170
124k
    size_t payload_size = 0;
171
124k
    size_t header_size = 1;
172
6.19M
    for (size_t i = 0; i < packet_count; i++) {
173
6.07M
        payload_size += packet_size[i];
174
6.07M
        if (i < packet_count - 1)
175
5.94M
            header_size += 1 + packet_size[i] / 255;
176
6.07M
    }
177
178
    /* */
179
124k
    *extra_size = header_size + payload_size;
180
124k
    *extra = malloc(*extra_size);
181
124k
    if (*extra == NULL)
182
0
        return VLC_ENOMEM;
183
184
    /* Write the header */
185
124k
    uint8_t *current = (uint8_t*)*extra;
186
124k
    *current++ = packet_count - 1;
187
6.07M
    for (size_t i = 0; i < packet_count - 1; i++) {
188
5.94M
        size_t t = packet_size[i];
189
6.05M
        for (;;) {
190
6.05M
            if (t >= 255) {
191
112k
                *current++ = 255;
192
112k
                t -= 255;
193
5.94M
            } else {
194
5.94M
                *current++ = t;
195
5.94M
                break;
196
5.94M
            }
197
6.05M
        }
198
5.94M
    }
199
200
    /* Copy the payloads */
201
6.19M
    for (size_t i = 0; i < packet_count; i++) {
202
6.07M
        if (packet_size[i] > 0) {
203
6.04M
            memcpy(current, packet[i], packet_size[i]);
204
6.04M
            current += packet_size[i];
205
6.04M
        }
206
6.07M
    }
207
124k
    assert(current == (uint8_t*)*extra + *extra_size);
208
124k
    return VLC_SUCCESS;
209
124k
}
matroska_segment_parse.cpp:xiph_PackHeaders(unsigned long*, void**, unsigned long*, void const* const*, unsigned long)
Line
Count
Source
165
11
{
166
11
    if (packet_count <= 0 || packet_count > XIPH_MAX_HEADER_COUNT)
167
0
        return VLC_EGENERIC;
168
169
    /* Compute the size needed for the whole extra data */
170
11
    size_t payload_size = 0;
171
11
    size_t header_size = 1;
172
33
    for (size_t i = 0; i < packet_count; i++) {
173
22
        payload_size += packet_size[i];
174
22
        if (i < packet_count - 1)
175
11
            header_size += 1 + packet_size[i] / 255;
176
22
    }
177
178
    /* */
179
11
    *extra_size = header_size + payload_size;
180
11
    *extra = malloc(*extra_size);
181
11
    if (*extra == NULL)
182
0
        return VLC_ENOMEM;
183
184
    /* Write the header */
185
11
    uint8_t *current = (uint8_t*)*extra;
186
11
    *current++ = packet_count - 1;
187
22
    for (size_t i = 0; i < packet_count - 1; i++) {
188
11
        size_t t = packet_size[i];
189
11
        for (;;) {
190
11
            if (t >= 255) {
191
0
                *current++ = 255;
192
0
                t -= 255;
193
11
            } else {
194
11
                *current++ = t;
195
11
                break;
196
11
            }
197
11
        }
198
11
    }
199
200
    /* Copy the payloads */
201
33
    for (size_t i = 0; i < packet_count; i++) {
202
22
        if (packet_size[i] > 0) {
203
19
            memcpy(current, packet[i], packet_size[i]);
204
19
            current += packet_size[i];
205
19
        }
206
22
    }
207
11
    assert(current == (uint8_t*)*extra + *extra_size);
208
11
    return VLC_SUCCESS;
209
11
}
210
211
static inline int xiph_AppendHeaders(size_t *extra_size, void **extra,
212
                                     size_t size, const void *data)
213
125k
{
214
125k
    size_t packet_size[XIPH_MAX_HEADER_COUNT];
215
125k
    const void *packet[XIPH_MAX_HEADER_COUNT];
216
125k
    size_t count;
217
218
125k
    if (*extra_size > 0 && *extra) {
219
63.6k
        if (xiph_SplitHeaders(packet_size, packet, &count, *extra_size, *extra))
220
0
            return VLC_EGENERIC;
221
63.6k
    } else {
222
61.4k
        count = 0;
223
61.4k
    }
224
125k
    if (count >= XIPH_MAX_HEADER_COUNT)
225
172
        return VLC_EGENERIC;
226
227
124k
    void *old = *extra;
228
229
124k
    packet_size[count] = size;
230
124k
    packet[count]      = (void*)data;
231
124k
    if (xiph_PackHeaders(extra_size, extra, packet_size,
232
124k
                         packet, count + 1)) {
233
0
        *extra_size = 0;
234
0
        *extra      = NULL;
235
0
    }
236
237
124k
    free(old);
238
239
124k
    if (*extra_size == 0)
240
0
        return VLC_EGENERIC;
241
124k
    return VLC_SUCCESS;
242
124k
}
Unexecuted instantiation: essetup.c:xiph_AppendHeaders
ogg.c:xiph_AppendHeaders
Line
Count
Source
213
125k
{
214
125k
    size_t packet_size[XIPH_MAX_HEADER_COUNT];
215
125k
    const void *packet[XIPH_MAX_HEADER_COUNT];
216
125k
    size_t count;
217
218
125k
    if (*extra_size > 0 && *extra) {
219
63.6k
        if (xiph_SplitHeaders(packet_size, packet, &count, *extra_size, *extra))
220
0
            return VLC_EGENERIC;
221
63.6k
    } else {
222
61.4k
        count = 0;
223
61.4k
    }
224
125k
    if (count >= XIPH_MAX_HEADER_COUNT)
225
172
        return VLC_EGENERIC;
226
227
124k
    void *old = *extra;
228
229
124k
    packet_size[count] = size;
230
124k
    packet[count]      = (void*)data;
231
124k
    if (xiph_PackHeaders(extra_size, extra, packet_size,
232
124k
                         packet, count + 1)) {
233
0
        *extra_size = 0;
234
0
        *extra      = NULL;
235
0
    }
236
237
124k
    free(old);
238
239
124k
    if (*extra_size == 0)
240
0
        return VLC_EGENERIC;
241
124k
    return VLC_SUCCESS;
242
124k
}
Unexecuted instantiation: matroska_segment_parse.cpp:xiph_AppendHeaders(unsigned long*, void**, unsigned long, void const*)