Coverage Report

Created: 2025-10-12 07:48

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
49.8M
static int BitWriterResize(VP8BitWriter* const bw, size_t extra_size) {
32
49.8M
  uint8_t* new_buf;
33
49.8M
  size_t new_size;
34
49.8M
  const uint64_t needed_size_64b = (uint64_t)bw->pos + extra_size;
35
49.8M
  const size_t needed_size = (size_t)needed_size_64b;
36
49.8M
  if (needed_size_64b != needed_size) {
37
0
    bw->error = 1;
38
0
    return 0;
39
0
  }
40
49.8M
  if (needed_size <= bw->max_pos) return 1;
41
  // If the following line wraps over 32bit, the test just after will catch it.
42
6.02k
  new_size = 2 * bw->max_pos;
43
6.02k
  if (new_size < needed_size) new_size = needed_size;
44
6.02k
  if (new_size < 1024) new_size = 1024;
45
6.02k
  new_buf = (uint8_t*)WebPSafeMalloc(1ULL, new_size);
46
6.02k
  if (new_buf == NULL) {
47
0
    bw->error = 1;
48
0
    return 0;
49
0
  }
50
6.02k
  if (bw->pos > 0) {
51
853
    assert(bw->buf != NULL);
52
853
    WEBP_UNSAFE_MEMCPY(new_buf, bw->buf, bw->pos);
53
853
  }
54
6.02k
  WebPSafeFree(bw->buf);
55
6.02k
  bw->buf = WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(uint8_t*, new_buf, new_size);
56
6.02k
  bw->max_pos = new_size;
57
6.02k
  return 1;
58
6.02k
}
59
60
50.2M
static void Flush(VP8BitWriter* const bw) {
61
50.2M
  const int s = 8 + bw->nb_bits;
62
50.2M
  const int32_t bits = bw->value >> s;
63
50.2M
  assert(bw->nb_bits >= 0);
64
50.2M
  bw->value -= bits << s;
65
50.2M
  bw->nb_bits -= 8;
66
50.2M
  if ((bits & 0xff) != 0xff) {
67
49.8M
    size_t pos = bw->pos;
68
49.8M
    if (!BitWriterResize(bw, bw->run + 1)) {
69
0
      return;
70
0
    }
71
49.8M
    if (bits & 0x100) {  // overflow -> propagate carry over pending 0xff's
72
8.00M
      if (pos > 0) bw->buf[pos - 1]++;
73
8.00M
    }
74
49.8M
    if (bw->run > 0) {
75
258k
      const int value = (bits & 0x100) ? 0x00 : 0xff;
76
674k
      for (; bw->run > 0; --bw->run) bw->buf[pos++] = value;
77
258k
    }
78
49.8M
    bw->buf[pos++] = bits & 0xff;
79
49.8M
    bw->pos = pos;
80
49.8M
  } else {
81
415k
    bw->run++;  // delay writing of bytes 0xff, pending eventual carry.
82
415k
  }
83
50.2M
}
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
670M
int VP8PutBit(VP8BitWriter* const bw, int bit, int prob) {
109
670M
  const int split = (bw->range * prob) >> 8;
110
670M
  if (bit) {
111
340M
    bw->value += split + 1;
112
340M
    bw->range -= split + 1;
113
340M
  } else {
114
330M
    bw->range = split;
115
330M
  }
116
670M
  if (bw->range < 127) {  // emit 'shift' bits out and renormalize
117
330M
    const int shift = kNorm[bw->range];
118
330M
    bw->range = kNewRange[bw->range];
119
330M
    bw->value <<= shift;
120
330M
    bw->nb_bits += shift;
121
330M
    if (bw->nb_bits > 0) Flush(bw);
122
330M
  }
123
670M
  return bit;
124
670M
}
125
126
937k
int VP8PutBitUniform(VP8BitWriter* const bw, int bit) {
127
937k
  const int split = bw->range >> 1;
128
937k
  if (bit) {
129
419k
    bw->value += split + 1;
130
419k
    bw->range -= split + 1;
131
518k
  } else {
132
518k
    bw->range = split;
133
518k
  }
134
937k
  if (bw->range < 127) {
135
935k
    bw->range = kNewRange[bw->range];
136
935k
    bw->value <<= 1;
137
935k
    bw->nb_bits += 1;
138
935k
    if (bw->nb_bits > 0) Flush(bw);
139
935k
  }
140
937k
  return bit;
141
937k
}
142
143
115k
void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits) {
144
115k
  uint32_t mask;
145
115k
  assert(nb_bits > 0 && nb_bits < 32);
146
1.01M
  for (mask = 1u << (nb_bits - 1); mask; mask >>= 1) {
147
897k
    VP8PutBitUniform(bw, value & mask);
148
897k
  }
149
115k
}
150
151
19.8k
void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) {
152
19.8k
  if (!VP8PutBitUniform(bw, value != 0)) return;
153
14.7k
  if (value < 0) {
154
2.94k
    VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1);
155
11.7k
  } else {
156
11.7k
    VP8PutBits(bw, value << 1, nb_bits + 1);
157
11.7k
  }
158
14.7k
}
159
160
//------------------------------------------------------------------------------
161
162
6.39k
int VP8BitWriterInit(VP8BitWriter* const bw, size_t expected_size) {
163
6.39k
  bw->range = 255 - 1;
164
6.39k
  bw->value = 0;
165
6.39k
  bw->run = 0;
166
6.39k
  bw->nb_bits = -8;
167
6.39k
  bw->pos = 0;
168
6.39k
  bw->max_pos = 0;
169
6.39k
  bw->error = 0;
170
6.39k
  bw->buf = NULL;
171
6.39k
  return (expected_size > 0) ? BitWriterResize(bw, expected_size) : 1;
172
6.39k
}
173
174
3.36k
uint8_t* VP8BitWriterFinish(VP8BitWriter* const bw) {
175
3.36k
  VP8PutBits(bw, 0, 9 - bw->nb_bits);
176
3.36k
  bw->nb_bits = 0;  // pad with zeroes
177
3.36k
  Flush(bw);
178
3.36k
  return bw->buf;
179
3.36k
}
180
181
int VP8BitWriterAppend(VP8BitWriter* const bw, const uint8_t* data,
182
3.61k
                       size_t size) {
183
3.61k
  assert(data != NULL);
184
3.61k
  if (bw->nb_bits != -8) return 0;  // Flush() must have been called
185
3.61k
  if (!BitWriterResize(bw, size)) return 0;
186
3.61k
  WEBP_UNSAFE_MEMCPY(bw->buf + bw->pos, data, size);
187
3.61k
  bw->pos += size;
188
3.61k
  return 1;
189
3.61k
}
190
191
4.53k
void VP8BitWriterWipeOut(VP8BitWriter* const bw) {
192
4.53k
  if (bw != NULL) {
193
4.53k
    WebPSafeFree(bw->buf);
194
4.53k
    WEBP_UNSAFE_MEMSET(bw, 0, sizeof(*bw));
195
4.53k
  }
196
4.53k
}
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
351
#define MIN_EXTRA_SIZE (32768ULL)
204
205
// Returns 1 on success.
206
14.7k
static int VP8LBitWriterResize(VP8LBitWriter* const bw, size_t extra_size) {
207
14.7k
  uint8_t* WEBP_BIDI_INDEXABLE allocated_buf;
208
14.7k
  size_t allocated_size;
209
14.7k
  const size_t max_bytes = bw->end - bw->buf;
210
14.7k
  const size_t current_size = bw->cur - bw->buf;
211
14.7k
  const uint64_t size_required_64b = (uint64_t)current_size + extra_size;
212
14.7k
  const size_t size_required = (size_t)size_required_64b;
213
14.7k
  if (size_required != size_required_64b) {
214
0
    bw->error = 1;
215
0
    return 0;
216
0
  }
217
14.7k
  if (max_bytes > 0 && size_required <= max_bytes) return 1;
218
11.0k
  allocated_size = (3 * max_bytes) >> 1;
219
11.0k
  if (allocated_size < size_required) allocated_size = size_required;
220
  // make allocated size multiple of 1k
221
11.0k
  allocated_size = (((allocated_size >> 10) + 1) << 10);
222
11.0k
  allocated_buf = (uint8_t*)WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(
223
11.0k
      void*, WebPSafeMalloc(1ULL, allocated_size), allocated_size);
224
11.0k
  if (allocated_buf == NULL) {
225
0
    bw->error = 1;
226
0
    return 0;
227
0
  }
228
11.0k
  if (current_size > 0) {
229
357
    WEBP_UNSAFE_MEMCPY(allocated_buf, bw->buf, current_size);
230
357
  }
231
11.0k
  WebPSafeFree(bw->buf);
232
11.0k
  bw->buf = allocated_buf;
233
11.0k
  bw->end = allocated_buf + allocated_size;
234
11.0k
  bw->cur = allocated_buf + current_size;
235
11.0k
  return 1;
236
11.0k
}
237
238
10.7k
int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) {
239
10.7k
  WEBP_UNSAFE_MEMSET(bw, 0, sizeof(*bw));
240
10.7k
  return VP8LBitWriterResize(bw, expected_size);
241
10.7k
}
242
243
int VP8LBitWriterClone(const VP8LBitWriter* const src,
244
1.04k
                       VP8LBitWriter* const dst) {
245
1.04k
  const size_t current_size = src->cur - src->buf;
246
1.04k
  assert(src->cur >= src->buf && src->cur <= src->end);
247
1.04k
  if (!VP8LBitWriterResize(dst, current_size)) return 0;
248
1.04k
  WEBP_UNSAFE_MEMCPY(dst->buf, src->buf, current_size);
249
1.04k
  dst->bits = src->bits;
250
1.04k
  dst->used = src->used;
251
1.04k
  dst->error = src->error;
252
1.04k
  dst->cur = dst->buf + current_size;
253
1.04k
  return 1;
254
1.04k
}
255
256
10.7k
void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) {
257
10.7k
  if (bw != NULL) {
258
10.7k
    WebPSafeFree(bw->buf);
259
10.7k
    WEBP_UNSAFE_MEMSET(bw, 0, sizeof(*bw));
260
10.7k
  }
261
10.7k
}
262
263
void VP8LBitWriterReset(const VP8LBitWriter* const bw_init,
264
3.72k
                        VP8LBitWriter* const bw) {
265
3.72k
  bw->bits = bw_init->bits;
266
3.72k
  bw->used = bw_init->used;
267
3.72k
  bw->cur = bw->buf + (bw_init->cur - bw_init->buf);
268
3.72k
  assert(bw->cur <= bw->end);
269
3.72k
  bw->error = bw_init->error;
270
3.72k
}
271
272
10.8k
void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst) {
273
10.8k
  const VP8LBitWriter tmp = *src;
274
10.8k
  *src = *dst;
275
10.8k
  *dst = tmp;
276
10.8k
}
277
278
void VP8LPutBitsFlushBits(VP8LBitWriter* const bw, int* used,
279
44.9M
                          vp8l_atype_t* bits) {
280
  // If needed, make some room by flushing some bits out.
281
44.9M
  if (bw->cur + VP8L_WRITER_BYTES > bw->end) {
282
351
    const uint64_t extra_size = (bw->end - bw->buf) + MIN_EXTRA_SIZE;
283
351
    if (!CheckSizeOverflow(extra_size) ||
284
351
        !VP8LBitWriterResize(bw, (size_t)extra_size)) {
285
0
      bw->cur = bw->buf;
286
0
      bw->error = 1;
287
0
      return;
288
0
    }
289
351
  }
290
44.9M
  *(vp8l_wtype_t*)bw->cur = (vp8l_wtype_t)WSWAP((vp8l_wtype_t)*bits);
291
44.9M
  bw->cur += VP8L_WRITER_BYTES;
292
44.9M
  *bits >>= VP8L_WRITER_BITS;
293
44.9M
  *used -= VP8L_WRITER_BITS;
294
44.9M
}
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
2.67k
uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw) {
328
  // flush leftover bits
329
2.67k
  if (VP8LBitWriterResize(bw, (bw->used + 7) >> 3)) {
330
10.9k
    while (bw->used > 0) {
331
8.31k
      *bw->cur++ = (uint8_t)bw->bits;
332
8.31k
      bw->bits >>= 8;
333
8.31k
      bw->used -= 8;
334
8.31k
    }
335
2.67k
    bw->used = 0;
336
2.67k
  }
337
2.67k
  return bw->buf;
338
2.67k
}
339
340
//------------------------------------------------------------------------------