Coverage Report

Created: 2026-06-30 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwebp/src/utils/huffman_utils.c
Line
Count
Source
1
// Copyright 2012 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
// Utilities for building and looking up Huffman trees.
11
//
12
// Author: Urvang Joshi (urvang@google.com)
13
14
#include "src/utils/huffman_utils.h"
15
16
#include <assert.h>
17
#include <stdlib.h>
18
#include <string.h>
19
20
#include "src/utils/bounds_safety.h"
21
#include "src/utils/utils.h"
22
#include "src/webp/format_constants.h"
23
#include "src/webp/types.h"
24
25
WEBP_ASSUME_UNSAFE_INDEXABLE_ABI
26
27
// Huffman data read via DecodeImageStream is represented in two (red and green)
28
// bytes.
29
#define MAX_HTREE_GROUPS 0x10000
30
31
5.20k
HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) {
32
5.20k
  HTreeGroup* const htree_groups =
33
5.20k
      (HTreeGroup*)WebPSafeMalloc(num_htree_groups, sizeof(*htree_groups));
34
5.20k
  if (htree_groups == NULL) {
35
0
    return NULL;
36
0
  }
37
5.20k
  assert(num_htree_groups <= MAX_HTREE_GROUPS);
38
5.20k
  return htree_groups;
39
5.20k
}
40
41
6.39k
void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) {
42
6.39k
  if (htree_groups != NULL) {
43
5.20k
    WebPSafeFree(htree_groups);
44
5.20k
  }
45
6.39k
}
46
47
// Returns reverse(reverse(key, len) + 1, len), where reverse(key, len) is the
48
// bit-wise reversal of the len least significant bits of key.
49
33.7k
static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) {
50
33.7k
  uint32_t step = 1 << (len - 1);
51
61.7k
  while (key & step) {
52
28.0k
    step >>= 1;
53
28.0k
  }
54
33.7k
  return step ? (key & (step - 1)) + step : key;
55
33.7k
}
56
57
// Stores code in table[0], table[step], table[2*step], ..., table[end-step].
58
// Assumes that end is an integer multiple of step.
59
static WEBP_INLINE void ReplicateValue(HuffmanCode* WEBP_COUNTED_BY(end - step +
60
                                                                    1) table,
61
59.4k
                                       int step, int end, HuffmanCode code) {
62
59.4k
  int current_end = end;
63
59.4k
  assert(current_end % step == 0);
64
10.1M
  do {
65
10.1M
    current_end -= step;
66
10.1M
    table[current_end] = code;
67
10.1M
  } while (current_end > 0);
68
59.4k
}
69
70
// Returns the table width of the next 2nd level table. count is the histogram
71
// of bit lengths for the remaining symbols, len is the code length of the next
72
// processed symbol
73
static WEBP_INLINE int NextTableBitSize(
74
    const int* const WEBP_COUNTED_BY(MAX_ALLOWED_CODE_LENGTH + 1) count,
75
1.05k
    int len, int root_bits) {
76
1.05k
  int left = 1 << (len - root_bits);
77
1.57k
  while (len < MAX_ALLOWED_CODE_LENGTH) {
78
1.50k
    left -= count[len];
79
1.50k
    if (left <= 0) break;
80
514
    ++len;
81
514
    left <<= 1;
82
514
  }
83
1.05k
  return len - root_bits;
84
1.05k
}
85
86
// sorted[code_lengths_size] is a pre-allocated array for sorting symbols
87
// by code length.
88
static int BuildHuffmanTable(HuffmanCode* const WEBP_BIDI_INDEXABLE root_table,
89
                             int root_bits, const int code_lengths[],
90
                             int code_lengths_size,
91
                             uint16_t WEBP_COUNTED_BY_OR_NULL(code_lengths_size)
92
82.9k
                                 sorted[]) {
93
  // next available space in table
94
82.9k
  HuffmanCode* WEBP_BIDI_INDEXABLE table = root_table;
95
82.9k
  int total_size = 1 << root_bits;  // total size root table + 2nd level table
96
82.9k
  int len;                          // current code length
97
82.9k
  int symbol;                       // symbol index in original or sorted table
98
  // number of codes of each length:
99
82.9k
  int count[MAX_ALLOWED_CODE_LENGTH + 1] = {0};
100
  // offsets in sorted table for each length:
101
82.9k
  int offset[MAX_ALLOWED_CODE_LENGTH + 1];
102
103
82.9k
  assert(code_lengths_size != 0);
104
82.9k
  assert(code_lengths != NULL);
105
82.9k
  assert((root_table != NULL && sorted != NULL) ||
106
82.9k
         (root_table == NULL && sorted == NULL));
107
82.9k
  assert(root_bits > 0);
108
109
  // Build histogram of code lengths.
110
19.3M
  for (symbol = 0; symbol < code_lengths_size; ++symbol) {
111
19.2M
    if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) {
112
0
      return 0;
113
0
    }
114
19.2M
    ++count[code_lengths[symbol]];
115
19.2M
  }
116
117
  // Error, all code lengths are zeros.
118
82.9k
  if (count[0] == code_lengths_size) {
119
28
    return 0;
120
28
  }
121
122
  // Generate offsets into sorted symbol table by code length.
123
82.8k
  offset[1] = 0;
124
1.24M
  for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) {
125
1.16M
    if (count[len] > (1 << len)) {
126
14
      return 0;
127
14
    }
128
1.16M
    offset[len + 1] = offset[len] + count[len];
129
1.16M
  }
130
131
  // Sort symbols by length, by symbol order within each length.
132
19.3M
  for (symbol = 0; symbol < code_lengths_size; ++symbol) {
133
19.2M
    const int symbol_code_length = code_lengths[symbol];
134
19.2M
    if (code_lengths[symbol] > 0) {
135
129k
      if (sorted != NULL) {
136
59.4k
        assert(offset[symbol_code_length] < code_lengths_size);
137
        // The following check is not redundant with the assert. It prevents a
138
        // potential buffer overflow that the optimizer might not be able to
139
        // rule out on its own.
140
59.4k
        if (offset[symbol_code_length] >= code_lengths_size) {
141
0
          return 0;
142
0
        }
143
59.4k
        sorted[offset[symbol_code_length]++] = symbol;
144
70.1k
      } else {
145
70.1k
        offset[symbol_code_length]++;
146
70.1k
      }
147
129k
    }
148
19.2M
  }
149
150
  // Special case code with only one value.
151
82.8k
  if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) {
152
71.5k
    if (sorted != NULL) {
153
34.5k
      HuffmanCode code;
154
34.5k
      code.bits = 0;
155
34.5k
      code.value = (uint16_t)sorted[0];
156
34.5k
      ReplicateValue(table, 1, total_size, code);
157
34.5k
    }
158
71.5k
    return total_size;
159
71.5k
  }
160
161
11.3k
  {
162
11.3k
    int step;  // step size to replicate values in current table
163
11.3k
    uint32_t low = 0xffffffffu;      // low bits for current root entry
164
11.3k
    uint32_t mask = total_size - 1;  // mask for low bits
165
11.3k
    uint32_t key = 0;                // reversed prefix code
166
11.3k
    int num_nodes = 1;               // number of Huffman tree nodes
167
11.3k
    int num_open = 1;  // number of open branches in current tree level
168
11.3k
    int table_bits = root_bits;        // key length of current table
169
11.3k
    int table_size = 1 << table_bits;  // size of current table
170
11.3k
    symbol = 0;
171
    // Fill in root table.
172
100k
    for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) {
173
89.6k
      num_open <<= 1;
174
89.6k
      num_nodes += num_open;
175
89.6k
      num_open -= count[len];
176
89.6k
      if (num_open < 0) {
177
13
        return 0;
178
13
      }
179
89.6k
      if (root_table == NULL) continue;
180
65.9k
      for (; count[len] > 0; --count[len]) {
181
22.9k
        HuffmanCode code;
182
22.9k
        code.bits = (uint8_t)len;
183
22.9k
        code.value = (uint16_t)sorted[symbol++];
184
22.9k
        ReplicateValue(&table[key], step, table_size, code);
185
22.9k
        key = GetNextKey(key, len);
186
22.9k
      }
187
43.0k
    }
188
189
    // Fill in 2nd level tables and add pointers to root table.
190
91.3k
    for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH;
191
80.0k
         ++len, step <<= 1) {
192
80.0k
      num_open <<= 1;
193
80.0k
      num_nodes += num_open;
194
80.0k
      num_open -= count[len];
195
80.0k
      if (num_open < 0) {
196
3
        return 0;
197
3
      }
198
90.8k
      for (; count[len] > 0; --count[len]) {
199
10.7k
        HuffmanCode code;
200
10.7k
        if ((key & mask) != low) {
201
1.05k
          if (root_table != NULL) table += table_size;
202
1.05k
          table_bits = NextTableBitSize(count, len, root_bits);
203
1.05k
          table_size = 1 << table_bits;
204
1.05k
          total_size += table_size;
205
1.05k
          low = key & mask;
206
1.05k
          if (root_table != NULL) {
207
316
            root_table[low].bits = (uint8_t)(table_bits + root_bits);
208
316
            root_table[low].value = (uint16_t)((table - root_table) - low);
209
316
          }
210
1.05k
        }
211
10.7k
        if (root_table != NULL) {
212
1.90k
          code.bits = (uint8_t)(len - root_bits);
213
1.90k
          code.value = (uint16_t)sorted[symbol++];
214
1.90k
          ReplicateValue(&table[key >> root_bits], step, table_size, code);
215
1.90k
        }
216
10.7k
        key = GetNextKey(key, len);
217
10.7k
      }
218
80.0k
    }
219
220
    // Check if tree is full.
221
11.3k
    if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {
222
70
      return 0;
223
70
    }
224
11.3k
  }
225
226
11.2k
  return total_size;
227
11.3k
}
228
229
// Maximum code_lengths_size is 2328 (reached for 11-bit color_cache_bits).
230
// More commonly, the value is around ~280.
231
#define MAX_CODE_LENGTHS_SIZE \
232
  ((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES)
233
// Cut-off value for switching between heap and stack allocation.
234
39.9k
#define SORTED_SIZE_CUTOFF 512
235
int VP8LBuildHuffmanTable(HuffmanTables* const root_table, int root_bits,
236
                          const int WEBP_COUNTED_BY(code_lengths_size)
237
                              code_lengths[],
238
42.9k
                          int code_lengths_size) {
239
42.9k
  const int total_size =
240
42.9k
      BuildHuffmanTable(NULL, root_bits, code_lengths, code_lengths_size, NULL);
241
42.9k
  assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);
242
42.9k
  if (total_size == 0 || root_table == NULL) return total_size;
243
244
39.9k
  if (root_table->curr_segment->curr_table + total_size >=
245
39.9k
      root_table->curr_segment->start + root_table->curr_segment->size) {
246
    // If 'root_table' does not have enough memory, allocate a new segment.
247
    // The available part of root_table->curr_segment is left unused because we
248
    // need a contiguous buffer.
249
490
    const int segment_size = root_table->curr_segment->size;
250
490
    struct HuffmanTablesSegment* next =
251
490
        (HuffmanTablesSegment*)WebPSafeMalloc(1, sizeof(*next));
252
490
    if (next == NULL) return 0;
253
    // Fill the new segment.
254
    // We need at least 'total_size' but if that value is small, it is better to
255
    // allocate a big chunk to prevent more allocations later. 'segment_size' is
256
    // therefore chosen (any other arbitrary value could be chosen).
257
490
    {
258
490
      const int next_size =
259
490
          total_size > segment_size ? total_size : segment_size;
260
490
      HuffmanCode* WEBP_BIDI_INDEXABLE const next_start =
261
490
          (HuffmanCode*)WebPSafeMalloc(next_size, sizeof(*next_start));
262
490
      if (next_start == NULL) {
263
0
        WebPSafeFree(next);
264
0
        return 0;
265
0
      }
266
490
      next->size = next_size;
267
490
      next->start = next_start;
268
490
    }
269
0
    next->curr_table = next->start;
270
490
    next->next = NULL;
271
    // Point to the new segment.
272
490
    root_table->curr_segment->next = next;
273
490
    root_table->curr_segment = next;
274
490
  }
275
39.9k
  if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
276
    // use local stack-allocated array.
277
39.2k
    uint16_t sorted[SORTED_SIZE_CUTOFF];
278
39.2k
    BuildHuffmanTable(
279
39.2k
        WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(
280
39.2k
            HuffmanCode*, root_table->curr_segment->curr_table,
281
39.2k
            total_size * sizeof(*root_table->curr_segment->curr_table)),
282
39.2k
        root_bits, code_lengths, code_lengths_size, sorted);
283
39.2k
  } else {  // rare case. Use heap allocation.
284
730
    uint16_t* const sorted =
285
730
        (uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
286
730
    if (sorted == NULL) return 0;
287
730
    BuildHuffmanTable(
288
730
        WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(
289
730
            HuffmanCode*, root_table->curr_segment->curr_table,
290
730
            total_size * sizeof(*root_table->curr_segment->curr_table)),
291
730
        root_bits, code_lengths, code_lengths_size,
292
730
        WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(
293
730
            uint16_t*, sorted, (size_t)code_lengths_size * sizeof(*sorted)));
294
730
    WebPSafeFree(sorted);
295
730
  }
296
39.9k
  return total_size;
297
39.9k
}
298
299
5.78k
int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables) {
300
  // Have 'segment' point to the first segment for now, 'root'.
301
5.78k
  HuffmanTablesSegment* const root = &huffman_tables->root;
302
5.78k
  huffman_tables->curr_segment = root;
303
5.78k
  root->next = NULL;
304
  // Allocate root.
305
5.78k
  {
306
5.78k
    HuffmanCode* WEBP_BIDI_INDEXABLE const start =
307
5.78k
        (HuffmanCode*)WebPSafeMalloc(size, sizeof(*root->start));
308
5.78k
    if (start == NULL) {
309
0
      root->start = NULL;
310
0
      root->size = 0;
311
0
      return 0;
312
0
    }
313
5.78k
    root->size = size;
314
5.78k
    root->start = start;
315
5.78k
  }
316
0
  root->curr_table = root->start;
317
5.78k
  return 1;
318
5.78k
}
319
320
6.96k
void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables) {
321
6.96k
  HuffmanTablesSegment *current, *next;
322
6.96k
  if (huffman_tables == NULL) return;
323
  // Free the root node.
324
6.96k
  current = &huffman_tables->root;
325
6.96k
  next = current->next;
326
6.96k
  WebPSafeFree(current->start);
327
6.96k
  current->start = NULL;
328
6.96k
  current->size = 0;
329
6.96k
  current->next = NULL;
330
6.96k
  current = next;
331
  // Free the following nodes.
332
7.45k
  while (current != NULL) {
333
490
    next = current->next;
334
490
    WebPSafeFree(current->start);
335
490
    WebPSafeFree(current);
336
490
    current = next;
337
490
  }
338
6.96k
}