Coverage Report

Created: 2026-09-06 07:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwebp/src/utils/bit_writer_utils.c
Line
Count
Source
1
// Copyright 2011 Google Inc. All Rights Reserved.
2
//
3
// Use of this source code is governed by a BSD-style license
4
// that can be found in the COPYING file in the root of the source
5
// tree. An additional intellectual property rights grant can be found
6
// in the file PATENTS. All contributing project authors may
7
// be found in the AUTHORS file in the root of the source tree.
8
// -----------------------------------------------------------------------------
9
//
10
// Bit writing and boolean coder
11
//
12
// Author: Skal (pascal.massimino@gmail.com)
13
//         Vikas Arora (vikaas.arora@gmail.com)
14
15
#include "src/utils/bit_writer_utils.h"
16
17
#include <assert.h>
18
#include <stdlib.h>
19
#include <string.h>  // for memcpy()
20
21
#include "src/utils/bounds_safety.h"
22
#include "src/utils/endian_inl_utils.h"
23
#include "src/utils/utils.h"
24
#include "src/webp/types.h"
25
26
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
27
28
//------------------------------------------------------------------------------
29
// VP8BitWriter
30
31
124M
static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) {
32
124M
  uint8_t* new_buf;
33
124M
  size_t new_size;
34
124M
  const uint64_t needed_size_64b = (uint64_t)bw->pos + extra_size;
35
124M
  const size_t needed_size = (size_t)needed_size_64b;
36
124M
  if (needed_size_64b != needed_size) {
37
0
    bw->error = 1;
38
0
    return 0;
39
0
  }
40
124M
  if (needed_size <= bw->max_pos) return 1;
41
  // If the following line wraps over 32bit, the test just after will catch it.
42
21.7k
  new_size = 2 * bw->max_pos;
43
21.7k
  if (new_size < needed_size) new_size = needed_size;
44
21.7k
  if (new_size < 1024) new_size = 1024;
45
21.7k
  new_buf = (uint8_t*)WebPSafeMalloc(1ULL, new_size);
46
21.7k
  if (new_buf == NULL) {
47
0
    bw->error = 1;
48
0
    return 0;
49
0
  }
50
21.7k
  if (bw->pos > 0) {
51
2.32k
    assert(bw->buf != NULL);
52
2.32k
    WEBP_UNSAFE_MEMCPY(new_buf, bw->buf, bw->pos);
53
2.32k
  }
54
21.7k
  WebPSafeFree(bw->buf);
55
21.7k
  bw->buf = WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, new_buf, new_size);
56
21.7k
  bw->max_pos = new_size;
57
21.7k
  return 1;
58
21.7k
}
59
60
125M
static void Flush(VP8BitWriter* const bw) {
61
125M
  const int s = 8 + bw->nb_bits;
62
125M
  const int32_t bits = bw->value >> s;
63
125M
  assert(bw->nb_bits >= 0);
64
125M
  bw->value -= bits << s;
65
125M
  bw->nb_bits -= 8;
66
125M
  if ((bits & 0xff) != 0xff) {
67
124M
    size_t pos = bw->pos;
68
124M
    if (!BitWriterResize(bw, bw->run + 1)) {
69
0
      return;
70
0
    }
71
124M
    if (bits & 0x100) {  // overflow -> propagate carry over pending 0xff's
72
19.8M
      if (pos > 0) bw->buf[pos - 1]++;
73
19.8M
    }
74
124M
    if (bw->run > 0) {
75
630k
      const int value = (bits & 0x100) ? 0x00 : 0xff;
76
1.59M
      for (; bw->run > 0; --bw->run) bw->buf[pos++] = value;
77
630k
    }
78
124M
    bw->buf[pos++] = bits & 0xff;
79
124M
    bw->pos = pos;
80
124M
  } else {
81
965k
    bw->run++;  // delay writing of bytes 0xff, pending eventual carry.
82
965k
  }
83
125M
}
84
85
//------------------------------------------------------------------------------
86
// renormalization
87
88
static const uint8_t kNorm[128] = {  // renorm_sizes[i] = 8 - log2(i)
89
    7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3,
90
    3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
91
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
92
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
93
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
94
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
95
96
// range = ((range + 1) << kVP8Log2Range[range]) - 1
97
static const uint8_t kNewRange[128] = {
98
    127, 127, 191, 127, 159, 191, 223, 127, 143, 159, 175, 191, 207, 223, 239,
99
    127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239,
100
    247, 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179,
101
    183, 187, 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239,
102
    243, 247, 251, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149,
103
    151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179,
104
    181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209,
105
    211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239,
106
    241, 243, 245, 247, 249, 251, 253, 127};
107
108
1.59G
int VP8PutBit(VP8BitWriter* const bw, int bit, int prob) {
109
1.59G
  const int split = (bw->range * prob) >> 8;
110
1.59G
  if (bit) {
111
838M
    bw->value += split + 1;
112
838M
    bw->range -= split + 1;
113
838M
  } else {
114
757M
    bw->range = split;
115
757M
  }
116
1.59G
  if (bw->range < 127) {  // emit 'shift' bits out and renormalize
117
812M
    const int shift = kNorm[bw->range];
118
812M
    bw->range = kNewRange[bw->range];
119
812M
    bw->value <<= shift;
120
812M
    bw->nb_bits += shift;
121
812M
    if (bw->nb_bits > 0) Flush(bw);
122
812M
  }
123
1.59G
  return bit;
124
1.59G
}
125
126
2.95M
int VP8PutBitUniform(VP8BitWriter* const bw, int bit) {
127
2.95M
  const int split = bw->range >> 1;
128
2.95M
  if (bit) {
129
1.24M
    bw->value += split + 1;
130
1.24M
    bw->range -= split + 1;
131
1.70M
  } else {
132
1.70M
    bw->range = split;
133
1.70M
  }
134
2.95M
  if (bw->range < 127) {
135
2.94M
    bw->range = kNewRange[bw->range];
136
2.94M
    bw->value <<= 1;
137
2.94M
    bw->nb_bits += 1;
138
2.94M
    if (bw->nb_bits > 0) Flush(bw);
139
2.94M
  }
140
2.95M
  return bit;
141
2.95M
}
142
143
360k
void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits) {
144
360k
  uint32_t mask;
145
360k
  assert(nb_bits > 0 && nb_bits < 32);
146
3.14M
  for (mask = 1u << (nb_bits - 1); mask; mask >>= 1) {
147
2.78M
    VP8PutBitUniform(bw, value & mask);
148
2.78M
  }
149
360k
}
150
151
82.0k
void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) {
152
82.0k
  if (!VP8PutBitUniform(bw, value != 0)) return;
153
62.0k
  if (value < 0) {
154
10.2k
    VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1);
155
51.8k
  } else {
156
51.8k
    VP8PutBits(bw, value << 1, nb_bits + 1);
157
51.8k
  }
158
62.0k
}
159
160
//------------------------------------------------------------------------------
161
162
23.6k
int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size) {
163
23.6k
  bw->range = 255 - 1;
164
23.6k
  bw->value = 0;
165
23.6k
  bw->run = 0;
166
23.6k
  bw->nb_bits = -8;
167
23.6k
  bw->pos = 0;
168
23.6k
  bw->max_pos = 0;
169
23.6k
  bw->error = 0;
170
23.6k
  bw->buf = NULL;
171
23.6k
  return (expected_size > 0) ? BitWriterResize(bw, expected_size) : 1;
172
23.6k
}
173
174
13.1k
uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) {
175
13.1k
  VP8PutBits(bw, 0, 9 - bw->nb_bits);
176
13.1k
  bw->nb_bits = 0;  // pad with zeroes
177
13.1k
  Flush(bw);
178
13.1k
  return bw->buf;
179
13.1k
}
180
181
int VP8BitWriterAppend(VP8BitWriter* const bw, const uint8_t* data,
182
12.6k
                       size_t size) {
183
12.6k
  assert(data != NULL);
184
12.6k
  if (bw->nb_bits != -8) return 0;  // Flush() must have been called
185
12.6k
  if (!BitWriterResize(bw, size)) return 0;
186
12.6k
  WEBP_UNSAFE_MEMCPY(bw->buf + bw->pos, data, size);
187
12.6k
  bw->pos += size;
188
12.6k
  return 1;
189
12.6k
}
190
191
17.3k
void VP8BitWriterWipeOut(VP8BitWriter* const bw) {
192
17.3k
  if (bw != NULL) {
193
17.3k
    WebPSafeFree(bw->buf);
194
17.3k
    WEBP_UNSAFE_MEMSET(bw, 0, sizeof(*bw));
195
17.3k
  }
196
17.3k
}
197
198
//------------------------------------------------------------------------------
199
// VP8LBitWriter
200
201
// This is the minimum amount of size the memory buffer is guaranteed to grow
202
// when extra space is needed.
203
930
#define MIN_EXTRA_SIZE (32768ULL)
204
205
// Returns 1 on success.
206
34.9k
static int VP8LBitWriterResize(VP8LBitWriter* const bw, size_t extra_size) {
207
34.9k
  uint8_t* WEBP_BIDI_INDEXABLE allocated_buf;
208
34.9k
  size_t allocated_size;
209
34.9k
  const size_t max_bytes = bw->end - bw->buf;
210
34.9k
  const size_t current_size = bw->cur - bw->buf;
211
34.9k
  const uint64_t size_required_64b = (uint64_t)current_size + extra_size;
212
34.9k
  const size_t size_required = (size_t)size_required_64b;
213
34.9k
  if (size_required != size_required_64b) {
214
0
    bw->error = 1;
215
0
    return 0;
216
0
  }
217
34.9k
  if (max_bytes > 0 && size_required <= max_bytes) return 1;
218
26.3k
  allocated_size = (3 * max_bytes) >> 1;
219
26.3k
  if (allocated_size < size_required) allocated_size = size_required;
220
  // make allocated size multiple of 1k
221
26.3k
  allocated_size = (((allocated_size >> 10) + 1) << 10);
222
26.3k
  allocated_buf = (uint8_t*)WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(
223
26.3k
      void*, WebPSafeMalloc(1ULL, allocated_size), allocated_size);
224
26.3k
  if (allocated_buf == NULL) {
225
0
    bw->error = 1;
226
0
    return 0;
227
0
  }
228
26.3k
  if (current_size > 0) {
229
936
    WEBP_UNSAFE_MEMCPY(allocated_buf, bw->buf, current_size);
230
936
  }
231
26.3k
  WebPSafeFree(bw->buf);
232
26.3k
  bw->buf = allocated_buf;
233
26.3k
  bw->end = allocated_buf + allocated_size;
234
26.3k
  bw->cur = allocated_buf + current_size;
235
26.3k
  return 1;
236
26.3k
}
237
238
25.3k
int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) {
239
25.3k
  WEBP_UNSAFE_MEMSET(bw, 0, sizeof(*bw));
240
25.3k
  return VP8LBitWriterResize(bw, expected_size);
241
25.3k
}
242
243
int VP8LBitWriterClone(const VP8LBitWriter* const src,
244
2.27k
                       VP8LBitWriter* const dst) {
245
2.27k
  const size_t current_size = src->cur - src->buf;
246
2.27k
  assert(src->cur >= src->buf && src->cur <= src->end);
247
2.27k
  if (!VP8LBitWriterResize(dst, current_size)) return 0;
248
2.27k
  WEBP_UNSAFE_MEMCPY(dst->buf, src->buf, current_size);
249
2.27k
  dst->bits = src->bits;
250
2.27k
  dst->used = src->used;
251
2.27k
  dst->error = src->error;
252
2.27k
  dst->cur = dst->buf + current_size;
253
2.27k
  return 1;
254
2.27k
}
255
256
25.3k
void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) {
257
25.3k
  if (bw != NULL) {
258
25.3k
    WebPSafeFree(bw->buf);
259
25.3k
    WEBP_UNSAFE_MEMSET(bw, 0, sizeof(*bw));
260
25.3k
  }
261
25.3k
}
262
263
void VP8LBitWriterReset(const VP8LBitWriter* const bw_init,
264
8.61k
                        VP8LBitWriter* const bw) {
265
8.61k
  bw->bits = bw_init->bits;
266
8.61k
  bw->used = bw_init->used;
267
8.61k
  bw->cur = bw->buf + (bw_init->cur - bw_init->buf);
268
8.61k
  assert(bw->cur <= bw->end);
269
8.61k
  bw->error = bw_init->error;
270
8.61k
}
271
272
25.8k
void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst) {
273
25.8k
  const VP8LBitWriter tmp = *src;
274
25.8k
  *src = *dst;
275
25.8k
  *dst = tmp;
276
25.8k
}
277
278
void VP8LPutBitsFlushBits(VP8LBitWriter* const bw, int* used,
279
46.8M
                          vp8l_atype_t* bits) {
280
  // If needed, make some room by flushing some bits out.
281
46.8M
  if (bw->cur + VP8L_WRITER_BYTES > bw->end) {
282
930
    const uint64_t extra_size = (bw->end - bw->buf) + MIN_EXTRA_SIZE;
283
930
    if (!CheckSizeOverflow(extra_size) ||
284
930
        !VP8LBitWriterResize(bw, (size_t)extra_size)) {
285
0
      bw->cur = bw->buf;
286
0
      bw->error = 1;
287
0
      return;
288
0
    }
289
930
  }
290
46.8M
  *(vp8l_wtype_t*)bw->cur = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)*bits);
291
46.8M
  bw->cur += VP8L_WRITER_BYTES;
292
46.8M
  *bits >>= VP8L_WRITER_BITS;
293
46.8M
  *used -= VP8L_WRITER_BITS;
294
46.8M
}
295
296
#if VP8L_WRITER_BITS == 16
297
void VP8LPutBitsInternal(VP8LBitWriter* const bw, uint32_t bits, int n_bits) {
298
  vp8l_atype_t lbits = bw->bits;
299
  int used = bw->used;
300
  assert(n_bits <= VP8L_WRITER_MAX_BITS);
301
  if (n_bits == 0) return;
302
  // Special case of overflow handling for 32bit accumulator (2-steps flush).
303
  if (used + n_bits >= VP8L_WRITER_MAX_BITS) {
304
    // Fill up all the VP8L_WRITER_MAX_BITS so it can be flushed out below.
305
    const int shift = VP8L_WRITER_MAX_BITS - used;
306
    lbits |= (vp8l_atype_t)bits << used;
307
    used = VP8L_WRITER_MAX_BITS;
308
    n_bits -= shift;
309
    if (shift >= (int)sizeof(bits) * 8) {
310
      // Undefined behavior.
311
      assert(shift == (int)sizeof(bits) * 8);
312
      bits = 0;
313
    } else {
314
      bits >>= shift;
315
    }
316
    assert(n_bits <= VP8L_WRITER_MAX_BITS);
317
  }
318
  // If needed, make some room by flushing some bits out.
319
  while (used >= VP8L_WRITER_BITS) {
320
    VP8LPutBitsFlushBits(bw, &used, &lbits);
321
  }
322
  bw->bits = lbits | ((vp8l_atype_t)bits << used);
323
  bw->used = used + n_bits;
324
}
325
#endif  // VP8L_WRITER_BITS == 16
326
327
6.34k
uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) {
328
  // flush leftover bits
329
6.34k
  if (VP8LBitWriterResize(bw, (bw->used + 7) >> 3)) {
330
25.2k
    while (bw->used > 0) {
331
18.8k
      *bw->cur++ = (uint8_t)bw->bits;
332
18.8k
      bw->bits >>= 8;
333
18.8k
      bw->used -= 8;
334
18.8k
    }
335
6.34k
    bw->used = 0;
336
6.34k
  }
337
6.34k
  return bw->buf;
338
6.34k
}
339
340
//------------------------------------------------------------------------------