Coverage Report

Created: 2026-10-17 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/libde265/libde265/nal-parser.cc
Line
Count
Source
1
/*
2
 * H.265 video codec.
3
 * Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de>
4
 *
5
 * This file is part of libde265.
6
 *
7
 * libde265 is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as
9
 * published by the Free Software Foundation, either version 3 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * libde265 is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with libde265.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include "nal-parser.h"
22
23
#include <string.h>
24
#include <assert.h>
25
#include <stdlib.h>
26
#include <stdio.h>
27
#include <stdint.h>
28
#include <limits.h>
29
#include <utility>
30
31
#ifdef HAVE_CONFIG_H
32
#include "config.h"
33
#endif
34
35
36
NAL_unit::~NAL_unit()
37
0
{
38
0
  free(nal_data);
39
0
}
40
41
[[nodiscard]] bool NAL_unit::resize(int new_size)
42
0
{
43
0
  if (capacity < new_size) {
44
    // Grow the buffer geometrically (1.5x) rather than to the exact requested
45
    // size. NAL_Parser::push_data() appends to the pending NAL one input chunk
46
    // at a time, increasing the request by a roughly constant amount each call.
47
    // With exact-size allocation every chunk would reallocate and copy the
48
    // whole accumulated buffer (O(n^2) for a single oversized NAL); spare
49
    // capacity amortizes the total copying to O(n). Here new_size > capacity >= 0,
50
    // so the 1.5x term is computed in 64 bits and only used when it both exceeds
51
    // the request and still fits in 'int'.
52
0
    int alloc_size = new_size;
53
0
    int64_t grow = static_cast<int64_t>(capacity) + capacity / 2;
54
0
    if (grow > new_size && grow <= INT_MAX) {
55
0
      alloc_size = static_cast<int>(grow);
56
0
    }
57
58
0
    unsigned char* newbuffer = static_cast<unsigned char*>(malloc(alloc_size));
59
0
    if (newbuffer == nullptr) {
60
0
      return false;
61
0
    }
62
63
0
    if (nal_data != nullptr) {
64
0
      memcpy(newbuffer, nal_data, data_size);
65
0
      free(nal_data);
66
0
    }
67
68
0
    nal_data = newbuffer;
69
0
    capacity = alloc_size;
70
0
  }
71
0
  return true;
72
0
}
73
74
[[nodiscard]] bool NAL_unit::append(const unsigned char* in_data, int n)
75
0
{
76
0
  if (!resize(data_size + n)) {
77
0
    return false;
78
0
  }
79
0
  if (n > 0) {
80
0
    memcpy(nal_data + data_size, in_data, n);
81
0
  }
82
0
  data_size += n;
83
0
  return true;
84
0
}
85
86
[[nodiscard]] bool NAL_unit::set_data(const unsigned char* in_data, int n)
87
0
{
88
0
  if (!resize(n)) {
89
0
    return false;
90
0
  }
91
0
  if (n > 0) {
92
0
    memcpy(nal_data, in_data, n);
93
0
  }
94
0
  data_size = n;
95
0
  return true;
96
0
}
97
98
void NAL_unit::insert_skipped_byte(uint32_t pos)
99
0
{
100
0
  skipped_bytes.push_back(pos);
101
0
}
102
103
uint32_t NAL_unit::num_skipped_bytes_before(uint32_t byte_position, uint32_t headerLength) const
104
0
{
105
0
  if (skipped_bytes.empty()) {
106
0
    return 0;
107
0
  }
108
109
0
  for (int k=skipped_bytes.size()-1;k>=0;k--)
110
0
    if (skipped_bytes[k] >= headerLength &&
111
0
        skipped_bytes[k]-headerLength <= byte_position) {
112
0
      return k+1;
113
0
    }
114
115
0
  return 0;
116
0
}
117
118
void NAL_unit::remove_stuffing_bytes()
119
0
{
120
  // Remove emulation-prevention bytes: every 0x03 that immediately follows two
121
  // 0x00 bytes is dropped (and the zero-run reset, so 00 00 03 03 keeps the
122
  // trailing 03). This is done in a single in-place forward-compaction pass in
123
  // O(n) time. A previous implementation called memmove() on the remaining tail
124
  // for each removed byte, which is O(n^2) and can be abused by a payload that
125
  // is densely packed with 00 00 03 triplets.
126
127
0
  uint8_t* d = data();
128
0
  const int n = size();
129
130
0
  int w = 0;       // write position == length of the compacted output so far
131
0
  int zeros = 0;   // number of consecutive 0x00 bytes already written to output
132
133
0
  for (int r=0; r<n; r++) {
134
0
    uint8_t b = d[r];
135
136
0
    if (zeros >= 2 && b == 3) {
137
      // 'r' is the position of this byte in the original (uncompacted) NAL,
138
      // which equals (compacted position) + num_skipped_bytes() — the value the
139
      // previous memmove-based code recorded here.
140
0
      insert_skipped_byte(r);
141
0
      zeros = 0;
142
0
      continue;
143
0
    }
144
145
0
    d[w++] = b;
146
0
    zeros = (b == 0) ? zeros + 1 : 0;
147
0
  }
148
149
0
  set_size(w);
150
0
}
151
152
153
154
155
156
0
NAL_Parser::NAL_Parser() = default;
157
158
159
NAL_Parser::~NAL_Parser()
160
0
{
161
  // The NAL queue and the pending input NAL hold owning unique_ptrs, so their
162
  // contents are released automatically. Nothing to do.
163
0
}
164
165
166
[[nodiscard]] std::unique_ptr<NAL_unit> NAL_Parser::alloc_NAL_unit(int size)
167
0
{
168
  // A freshly constructed NAL_unit is already in the cleared state (empty
169
  // buffer, empty skipped-byte list), so no clear() is needed here.
170
0
  auto nal = std::make_unique<NAL_unit>();
171
172
0
  if (!nal->resize(size)) {
173
0
    return nullptr;   // 'nal' is deleted as it goes out of scope
174
0
  }
175
176
0
  return nal;
177
0
}
178
179
void NAL_Parser::free_NAL_unit(std::unique_ptr<NAL_unit> /*nal*/)
180
0
{
181
  // Releasing a NAL is just destroying it: ownership is moved in by value, so the
182
  // NAL is deleted when the argument goes out of scope here (a moved-from / null
183
  // argument is a harmless no-op). Kept as a named operation so call sites read as
184
  // an explicit release, and because it makes a double release impossible to express.
185
0
}
186
187
std::unique_ptr<NAL_unit> NAL_Parser::pop_from_NAL_queue()
188
0
{
189
0
  if (NAL_queue.empty()) {
190
0
    return nullptr;
191
0
  }
192
0
  else {
193
0
    std::unique_ptr<NAL_unit> nal = std::move(NAL_queue.front());
194
0
    NAL_queue.pop();
195
196
0
    nBytes_in_NAL_queue -= nal->size();
197
198
0
    return nal;
199
0
  }
200
0
}
201
202
void NAL_Parser::push_to_NAL_queue(std::unique_ptr<NAL_unit> nal)
203
0
{
204
0
  nBytes_in_NAL_queue += nal->size();
205
0
  NAL_queue.push(std::move(nal));
206
0
}
207
208
de265_error NAL_Parser::push_data(const unsigned char* data, int len,
209
                                  de265_PTS pts, void* user_data)
210
0
{
211
0
  end_of_frame = false;
212
213
0
  if (pending_input_NAL == nullptr) {
214
0
    pending_input_NAL = alloc_NAL_unit(len+3);
215
0
    if (pending_input_NAL == nullptr) {
216
0
      return DE265_ERROR_OUT_OF_MEMORY;
217
0
    }
218
0
    pending_input_NAL->pts = pts;
219
0
    pending_input_NAL->user_data = user_data;
220
0
  }
221
222
  // Raw working pointer for byte access; ownership stays in pending_input_NAL.
223
0
  NAL_unit* nal = pending_input_NAL.get(); // shortcut
224
225
  // Resize output buffer so that complete input would fit.
226
  // We add 3, because in the worst case 3 extra bytes are created for an input byte.
227
0
  if (!nal->resize(nal->size() + len + 3)) {
228
0
    return DE265_ERROR_OUT_OF_MEMORY;
229
0
  }
230
231
0
  unsigned char* out = nal->data() + nal->size();
232
233
0
  for (int i=0;i<len;i++) {
234
    /*
235
    printf("state=%d input=%02x (%p) (output size: %d)\n",ctx->input_push_state, *data, data,
236
           out - ctx->nal_data.data);
237
    */
238
239
0
    switch (input_push_state) {
240
0
    case 0:
241
0
    case 1:
242
0
      if (*data == 0) { input_push_state++; }
243
0
      else { input_push_state=0; }
244
0
      break;
245
0
    case 2:
246
0
      if      (*data == 1) { input_push_state=3; } // nal->clear_skipped_bytes(); }
247
0
      else if (*data == 0) { } // *out++ = 0; }
248
0
      else { input_push_state=0; }
249
0
      break;
250
0
    case 3:
251
0
      *out++ = *data;
252
0
      input_push_state = 4;
253
0
      break;
254
0
    case 4:
255
0
      *out++ = *data;
256
0
      input_push_state = 5;
257
0
      break;
258
259
0
    case 5:
260
0
      if (*data==0) { input_push_state=6; }
261
0
      else { *out++ = *data; }
262
0
      break;
263
264
0
    case 6:
265
0
      if (*data==0) { input_push_state=7; }
266
0
      else {
267
0
        *out++ = 0;
268
0
        *out++ = *data;
269
0
        input_push_state=5;
270
0
      }
271
0
      break;
272
273
0
    case 7:
274
0
      if      (*data==0) { *out++ = 0; }
275
0
      else if (*data==3) {
276
0
        *out++ = 0; *out++ = 0; input_push_state=5;
277
278
        // remember which byte we removed
279
0
        nal->insert_skipped_byte((out - nal->data()) + nal->num_skipped_bytes());
280
0
      }
281
0
      else if (*data==1) {
282
283
#if DEBUG_INSERT_STREAM_ERRORS
284
        if ((rand()%100)<90 && nal_data.size>0) {
285
          int pos = rand()%nal_data.size;
286
          int bit = rand()%8;
287
          nal->nal_data.data[pos] ^= 1<<bit;
288
289
          //printf("inserted error...\n");
290
        }
291
#endif
292
293
        // enforce the maximum NAL size: drop an oversized NAL and resync
294
0
        if (!nal_size_within_limit(out - nal->data())) {
295
0
          free_NAL_unit(std::move(pending_input_NAL));
296
0
          input_push_state = 0;
297
0
          return DE265_ERROR_NAL_SIZE_EXCEEDS_SECURITY_LIMIT;
298
0
        }
299
300
0
        nal->set_size(out - nal->data());;
301
302
        // push this completed NAL onto the decoder queue (transfers ownership)
303
0
        push_to_NAL_queue(std::move(pending_input_NAL));
304
305
306
        // initialize new, empty NAL unit
307
308
0
        pending_input_NAL = alloc_NAL_unit(len+3);
309
0
        if (pending_input_NAL == nullptr) {
310
0
          return DE265_ERROR_OUT_OF_MEMORY;
311
0
        }
312
0
        pending_input_NAL->pts = pts;
313
0
        pending_input_NAL->user_data = user_data;
314
0
        nal = pending_input_NAL.get();
315
0
        out = nal->data();
316
317
0
        input_push_state=3;
318
        //nal->clear_skipped_bytes();
319
0
      }
320
0
      else {
321
0
        *out++ = 0;
322
0
        *out++ = 0;
323
0
        *out++ = *data;
324
325
0
        input_push_state=5;
326
0
      }
327
0
      break;
328
0
    }
329
330
0
    data++;
331
0
  }
332
333
0
  nal->set_size(out - nal->data());
334
335
  // Enforce the maximum NAL size on the still-incomplete pending NAL. This bounds
336
  // memory when a single NAL grows across many push_data() calls without ever
337
  // reaching a start code. The oversized pending NAL is dropped and the parser
338
  // resyncs at the next start code.
339
0
  if (!nal_size_within_limit(nal->size())) {
340
0
    free_NAL_unit(std::move(pending_input_NAL));
341
0
    input_push_state = 0;
342
0
    return DE265_ERROR_NAL_SIZE_EXCEEDS_SECURITY_LIMIT;
343
0
  }
344
345
0
  return DE265_OK;
346
0
}
347
348
349
de265_error NAL_Parser::push_NAL(const unsigned char* data, int len,
350
                                 de265_PTS pts, void* user_data)
351
0
{
352
353
  // Cannot use byte-stream input and NAL input at the same time.
354
0
  assert(pending_input_NAL == nullptr);
355
356
  // A NAL unit must at least contain its two-byte header. Reject anything shorter
357
  // (including a negative length) before touching any state: a zero-length unit
358
  // would otherwise end up as a memcpy() with a NULL destination and, once queued,
359
  // would fail header parsing in decode_NAL() and abort decoding of the stream.
360
0
  if (len < 2) {
361
0
    return DE265_ERROR_INVALID_ARGUMENT;
362
0
  }
363
364
0
  end_of_frame = false;
365
366
  // enforce the maximum NAL size to bound memory usage
367
0
  if (!nal_size_within_limit(len)) {
368
0
    return DE265_ERROR_NAL_SIZE_EXCEEDS_SECURITY_LIMIT;
369
0
  }
370
371
0
  std::unique_ptr<NAL_unit> nal = alloc_NAL_unit(len);
372
0
  if (nal == nullptr || !nal->set_data(data, len)) {
373
0
    free_NAL_unit(std::move(nal));
374
0
    return DE265_ERROR_OUT_OF_MEMORY;
375
0
  }
376
0
  nal->pts = pts;
377
0
  nal->user_data = user_data;
378
379
0
  nal->remove_stuffing_bytes();
380
381
0
  push_to_NAL_queue(std::move(nal));
382
383
0
  return DE265_OK;
384
0
}
385
386
387
de265_error NAL_Parser::flush_data()
388
0
{
389
0
  if (pending_input_NAL) {
390
0
    NAL_unit* nal = pending_input_NAL.get();
391
0
    uint8_t null[2] = { 0,0 };
392
393
    // append bytes that are implied by the push state
394
395
0
    if (input_push_state==6) {
396
0
      if (!nal->append(null,1)) {
397
0
        return DE265_ERROR_OUT_OF_MEMORY;
398
0
      }
399
0
    }
400
0
    if (input_push_state==7) {
401
0
      if (!nal->append(null,2)) {
402
0
        return DE265_ERROR_OUT_OF_MEMORY;
403
0
      }
404
0
    }
405
406
407
    // only push the NAL if it contains at least the NAL header
408
409
0
    if (input_push_state>=5) {
410
0
      push_to_NAL_queue(std::move(pending_input_NAL));
411
0
    }
412
413
0
    input_push_state = 0;
414
0
  }
415
416
0
  return DE265_OK;
417
0
}
418
419
420
void NAL_Parser::remove_pending_input_data()
421
0
{
422
  // --- remove pending input data ---
423
424
0
  if (pending_input_NAL) {
425
0
    free_NAL_unit(std::move(pending_input_NAL));
426
0
  }
427
428
0
  for (;;) {
429
0
    std::unique_ptr<NAL_unit> nal = pop_from_NAL_queue();
430
0
    if (nal) { free_NAL_unit(std::move(nal)); }
431
0
    else break;
432
0
  }
433
434
0
  input_push_state = 0;
435
0
  nBytes_in_NAL_queue = 0;
436
0
}