Coverage Report

Created: 2022-08-24 06:15

/src/aom/aom/src/aom_integer.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2018, Alliance for Open Media. All rights reserved
3
 *
4
 * This source code is subject to the terms of the BSD 2 Clause License and
5
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6
 * was not distributed with this source code in the LICENSE file, you can
7
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8
 * Media Patent License 1.0 was not distributed with this source code in the
9
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10
 */
11
#include <assert.h>
12
13
#include "aom/aom_integer.h"
14
15
static const size_t kMaximumLeb128Size = 8;
16
static const uint8_t kLeb128ByteMask = 0x7f;  // Binary: 01111111
17
18
// Disallow values larger than 32-bits to ensure consistent behavior on 32 and
19
// 64 bit targets: value is typically used to determine buffer allocation size
20
// when decoded.
21
static const uint64_t kMaximumLeb128Value = UINT32_MAX;
22
23
7.57k
size_t aom_uleb_size_in_bytes(uint64_t value) {
24
7.57k
  size_t size = 0;
25
7.57k
  do {
26
7.57k
    ++size;
27
7.57k
  } while ((value >>= 7) != 0);
28
7.57k
  return size;
29
7.57k
}
30
31
int aom_uleb_decode(const uint8_t *buffer, size_t available, uint64_t *value,
32
0
                    size_t *length) {
33
0
  if (buffer && value) {
34
0
    *value = 0;
35
0
    for (size_t i = 0; i < kMaximumLeb128Size && i < available; ++i) {
36
0
      const uint8_t decoded_byte = *(buffer + i) & kLeb128ByteMask;
37
0
      *value |= ((uint64_t)decoded_byte) << (i * 7);
38
0
      if ((*(buffer + i) >> 7) == 0) {
39
0
        if (length) {
40
0
          *length = i + 1;
41
0
        }
42
43
        // Fail on values larger than 32-bits to ensure consistent behavior on
44
        // 32 and 64 bit targets: value is typically used to determine buffer
45
        // allocation size.
46
0
        if (*value > UINT32_MAX) return -1;
47
48
0
        return 0;
49
0
      }
50
0
    }
51
0
  }
52
53
  // If we get here, either the buffer/value pointers were invalid,
54
  // or we ran over the available space
55
0
  return -1;
56
0
}
57
58
int aom_uleb_encode(uint64_t value, size_t available, uint8_t *coded_value,
59
3.78k
                    size_t *coded_size) {
60
3.78k
  const size_t leb_size = aom_uleb_size_in_bytes(value);
61
3.78k
  if (value > kMaximumLeb128Value || leb_size > kMaximumLeb128Size ||
62
3.78k
      leb_size > available || !coded_value || !coded_size) {
63
0
    return -1;
64
0
  }
65
66
7.57k
  for (size_t i = 0; i < leb_size; ++i) {
67
3.78k
    uint8_t byte = value & 0x7f;
68
3.78k
    value >>= 7;
69
70
3.78k
    if (value != 0) byte |= 0x80;  // Signal that more bytes follow.
71
72
3.78k
    *(coded_value + i) = byte;
73
3.78k
  }
74
75
3.78k
  *coded_size = leb_size;
76
3.78k
  return 0;
77
3.78k
}
78
79
int aom_uleb_encode_fixed_size(uint64_t value, size_t available,
80
                               size_t pad_to_size, uint8_t *coded_value,
81
0
                               size_t *coded_size) {
82
0
  if (value > kMaximumLeb128Value || !coded_value || !coded_size ||
83
0
      available < pad_to_size || pad_to_size > kMaximumLeb128Size) {
84
0
    return -1;
85
0
  }
86
0
  const uint64_t limit = 1ULL << (7 * pad_to_size);
87
0
  if (value >= limit) {
88
    // Can't encode 'value' within 'pad_to_size' bytes
89
0
    return -1;
90
0
  }
91
92
0
  for (size_t i = 0; i < pad_to_size; ++i) {
93
0
    uint8_t byte = value & 0x7f;
94
0
    value >>= 7;
95
96
0
    if (i < pad_to_size - 1) byte |= 0x80;  // Signal that more bytes follow.
97
98
0
    *(coded_value + i) = byte;
99
0
  }
100
101
0
  assert(value == 0);
102
103
0
  *coded_size = pad_to_size;
104
0
  return 0;
105
0
}