Coverage Report

Created: 2025-12-31 07:15

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
2.33k
HTreeGroup* VP8LHtreeGroupsNew(int num_htree_groups) {
32
2.33k
  HTreeGroup* const htree_groups =
33
2.33k
      (HTreeGroup*)WebPSafeMalloc(num_htree_groups, sizeof(*htree_groups));
34
2.33k
  if (htree_groups == NULL) {
35
0
    return NULL;
36
0
  }
37
2.33k
  assert(num_htree_groups <= MAX_HTREE_GROUPS);
38
2.33k
  return htree_groups;
39
2.33k
}
40
41
5.37k
void VP8LHtreeGroupsFree(HTreeGroup* const htree_groups) {
42
5.37k
  if (htree_groups != NULL) {
43
2.33k
    WebPSafeFree(htree_groups);
44
2.33k
  }
45
5.37k
}
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
124k
static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) {
50
124k
  uint32_t step = 1 << (len - 1);
51
244k
  while (key & step) {
52
119k
    step >>= 1;
53
119k
  }
54
124k
  return step ? (key & (step - 1)) + step : key;
55
124k
}
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
95.5k
                                       int step, int end, HuffmanCode code) {
62
95.5k
  int current_end = end;
63
95.5k
  assert(current_end % step == 0);
64
8.35M
  do {
65
8.35M
    current_end -= step;
66
8.35M
    table[current_end] = code;
67
8.35M
  } while (current_end > 0);
68
95.5k
}
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
13.6k
    int len, int root_bits) {
76
13.6k
  int left = 1 << (len - root_bits);
77
14.9k
  while (len < MAX_ALLOWED_CODE_LENGTH) {
78
14.8k
    left -= count[len];
79
14.8k
    if (left <= 0) break;
80
1.35k
    ++len;
81
1.35k
    left <<= 1;
82
1.35k
  }
83
13.6k
  return len - root_bits;
84
13.6k
}
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
896k
                                 sorted[]) {
93
  // next available space in table
94
896k
  HuffmanCode* WEBP_BIDI_INDEXABLE table = root_table;
95
896k
  int total_size = 1 << root_bits;  // total size root table + 2nd level table
96
896k
  int len;                          // current code length
97
896k
  int symbol;                       // symbol index in original or sorted table
98
  // number of codes of each length:
99
896k
  int count[MAX_ALLOWED_CODE_LENGTH + 1] = {0};
100
  // offsets in sorted table for each length:
101
896k
  int offset[MAX_ALLOWED_CODE_LENGTH + 1];
102
103
896k
  assert(code_lengths_size != 0);
104
896k
  assert(code_lengths != NULL);
105
896k
  assert((root_table != NULL && sorted != NULL) ||
106
896k
         (root_table == NULL && sorted == NULL));
107
896k
  assert(root_bits > 0);
108
109
  // Build histogram of code lengths.
110
197M
  for (symbol = 0; symbol < code_lengths_size; ++symbol) {
111
197M
    if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) {
112
0
      return 0;
113
0
    }
114
197M
    ++count[code_lengths[symbol]];
115
197M
  }
116
117
  // Error, all code lengths are zeros.
118
896k
  if (count[0] == code_lengths_size) {
119
95
    return 0;
120
95
  }
121
122
  // Generate offsets into sorted symbol table by code length.
123
896k
  offset[1] = 0;
124
13.4M
  for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) {
125
12.5M
    if (count[len] > (1 << len)) {
126
18
      return 0;
127
18
    }
128
12.5M
    offset[len + 1] = offset[len] + count[len];
129
12.5M
  }
130
131
  // Sort symbols by length, by symbol order within each length.
132
197M
  for (symbol = 0; symbol < code_lengths_size; ++symbol) {
133
197M
    const int symbol_code_length = code_lengths[symbol];
134
197M
    if (code_lengths[symbol] > 0) {
135
1.04M
      if (sorted != NULL) {
136
95.5k
        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
95.5k
        if (offset[symbol_code_length] >= code_lengths_size) {
141
0
          return 0;
142
0
        }
143
95.5k
        sorted[offset[symbol_code_length]++] = symbol;
144
952k
      } else {
145
952k
        offset[symbol_code_length]++;
146
952k
      }
147
1.04M
    }
148
197M
  }
149
150
  // Special case code with only one value.
151
896k
  if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) {
152
885k
    if (sorted != NULL) {
153
28.4k
      HuffmanCode code;
154
28.4k
      code.bits = 0;
155
28.4k
      code.value = (uint16_t)sorted[0];
156
28.4k
      ReplicateValue(table, 1, total_size, code);
157
28.4k
    }
158
885k
    return total_size;
159
885k
  }
160
161
10.8k
  {
162
10.8k
    int step;  // step size to replicate values in current table
163
10.8k
    uint32_t low = 0xffffffffu;      // low bits for current root entry
164
10.8k
    uint32_t mask = total_size - 1;  // mask for low bits
165
10.8k
    uint32_t key = 0;                // reversed prefix code
166
10.8k
    int num_nodes = 1;               // number of Huffman tree nodes
167
10.8k
    int num_open = 1;  // number of open branches in current tree level
168
10.8k
    int table_bits = root_bits;        // key length of current table
169
10.8k
    int table_size = 1 << table_bits;  // size of current table
170
10.8k
    symbol = 0;
171
    // Fill in root table.
172
94.9k
    for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) {
173
84.1k
      num_open <<= 1;
174
84.1k
      num_nodes += num_open;
175
84.1k
      num_open -= count[len];
176
84.1k
      if (num_open < 0) {
177
14
        return 0;
178
14
      }
179
84.1k
      if (root_table == NULL) continue;
180
65.1k
      for (; count[len] > 0; --count[len]) {
181
28.5k
        HuffmanCode code;
182
28.5k
        code.bits = (uint8_t)len;
183
28.5k
        code.value = (uint16_t)sorted[symbol++];
184
28.5k
        ReplicateValue(&table[key], step, table_size, code);
185
28.5k
        key = GetNextKey(key, len);
186
28.5k
      }
187
36.5k
    }
188
189
    // Fill in 2nd level tables and add pointers to root table.
190
89.1k
    for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH;
191
78.3k
         ++len, step <<= 1) {
192
78.3k
      num_open <<= 1;
193
78.3k
      num_nodes += num_open;
194
78.3k
      num_open -= count[len];
195
78.3k
      if (num_open < 0) {
196
9
        return 0;
197
9
      }
198
174k
      for (; count[len] > 0; --count[len]) {
199
96.4k
        HuffmanCode code;
200
96.4k
        if ((key & mask) != low) {
201
13.6k
          if (root_table != NULL) table += table_size;
202
13.6k
          table_bits = NextTableBitSize(count, len, root_bits);
203
13.6k
          table_size = 1 << table_bits;
204
13.6k
          total_size += table_size;
205
13.6k
          low = key & mask;
206
13.6k
          if (root_table != NULL) {
207
5.80k
            root_table[low].bits = (uint8_t)(table_bits + root_bits);
208
5.80k
            root_table[low].value = (uint16_t)((table - root_table) - low);
209
5.80k
          }
210
13.6k
        }
211
96.4k
        if (root_table != NULL) {
212
38.5k
          code.bits = (uint8_t)(len - root_bits);
213
38.5k
          code.value = (uint16_t)sorted[symbol++];
214
38.5k
          ReplicateValue(&table[key >> root_bits], step, table_size, code);
215
38.5k
        }
216
96.4k
        key = GetNextKey(key, len);
217
96.4k
      }
218
78.3k
    }
219
220
    // Check if tree is full.
221
10.8k
    if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {
222
76
      return 0;
223
76
    }
224
10.8k
  }
225
226
10.7k
  return total_size;
227
10.8k
}
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
33.1k
#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
863k
                          int code_lengths_size) {
239
863k
  const int total_size =
240
863k
      BuildHuffmanTable(NULL, root_bits, code_lengths, code_lengths_size, NULL);
241
863k
  assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);
242
863k
  if (total_size == 0 || root_table == NULL) return total_size;
243
244
33.1k
  if (root_table->curr_segment->curr_table + total_size >=
245
33.1k
      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
1.44k
    const int segment_size = root_table->curr_segment->size;
250
1.44k
    struct HuffmanTablesSegment* next =
251
1.44k
        (HuffmanTablesSegment*)WebPSafeMalloc(1, sizeof(*next));
252
1.44k
    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
1.44k
    {
258
1.44k
      const int next_size =
259
1.44k
          total_size > segment_size ? total_size : segment_size;
260
1.44k
      HuffmanCode* WEBP_BIDI_INDEXABLE const next_start =
261
1.44k
          (HuffmanCode*)WebPSafeMalloc(next_size, sizeof(*next_start));
262
1.44k
      if (next_start == NULL) {
263
0
        WebPSafeFree(next);
264
0
        return 0;
265
0
      }
266
1.44k
      next->size = next_size;
267
1.44k
      next->start = next_start;
268
1.44k
    }
269
0
    next->curr_table = next->start;
270
1.44k
    next->next = NULL;
271
    // Point to the new segment.
272
1.44k
    root_table->curr_segment->next = next;
273
1.44k
    root_table->curr_segment = next;
274
1.44k
  }
275
33.1k
  if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
276
    // use local stack-allocated array.
277
31.8k
    uint16_t sorted[SORTED_SIZE_CUTOFF];
278
31.8k
    BuildHuffmanTable(
279
31.8k
        WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(
280
31.8k
            HuffmanCode*, root_table->curr_segment->curr_table,
281
31.8k
            total_size * sizeof(*root_table->curr_segment->curr_table)),
282
31.8k
        root_bits, code_lengths, code_lengths_size, sorted);
283
31.8k
  } else {  // rare case. Use heap allocation.
284
1.36k
    uint16_t* const sorted =
285
1.36k
        (uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
286
1.36k
    if (sorted == NULL) return 0;
287
1.36k
    BuildHuffmanTable(
288
1.36k
        WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(
289
1.36k
            HuffmanCode*, root_table->curr_segment->curr_table,
290
1.36k
            total_size * sizeof(*root_table->curr_segment->curr_table)),
291
1.36k
        root_bits, code_lengths, code_lengths_size,
292
1.36k
        WEBP_UNSAFE_FORGE_BIDI_INDEXABLE(
293
1.36k
            uint16_t*, sorted, (size_t)code_lengths_size * sizeof(*sorted)));
294
1.36k
    WebPSafeFree(sorted);
295
1.36k
  }
296
33.1k
  return total_size;
297
33.1k
}
298
299
3.91k
int VP8LHuffmanTablesAllocate(int size, HuffmanTables* huffman_tables) {
300
  // Have 'segment' point to the first segment for now, 'root'.
301
3.91k
  HuffmanTablesSegment* const root = &huffman_tables->root;
302
3.91k
  huffman_tables->curr_segment = root;
303
3.91k
  root->next = NULL;
304
  // Allocate root.
305
3.91k
  {
306
3.91k
    HuffmanCode* WEBP_BIDI_INDEXABLE const start =
307
3.91k
        (HuffmanCode*)WebPSafeMalloc(size, sizeof(*root->start));
308
3.91k
    if (start == NULL) {
309
0
      root->start = NULL;
310
0
      root->size = 0;
311
0
      return 0;
312
0
    }
313
3.91k
    root->size = size;
314
3.91k
    root->start = start;
315
3.91k
  }
316
0
  root->curr_table = root->start;
317
3.91k
  return 1;
318
3.91k
}
319
320
6.94k
void VP8LHuffmanTablesDeallocate(HuffmanTables* const huffman_tables) {
321
6.94k
  HuffmanTablesSegment *current, *next;
322
6.94k
  if (huffman_tables == NULL) return;
323
  // Free the root node.
324
6.94k
  current = &huffman_tables->root;
325
6.94k
  next = current->next;
326
6.94k
  WebPSafeFree(current->start);
327
6.94k
  current->start = NULL;
328
6.94k
  current->size = 0;
329
6.94k
  current->next = NULL;
330
6.94k
  current = next;
331
  // Free the following nodes.
332
8.39k
  while (current != NULL) {
333
1.44k
    next = current->next;
334
1.44k
    WebPSafeFree(current->start);
335
1.44k
    WebPSafeFree(current);
336
1.44k
    current = next;
337
1.44k
  }
338
6.94k
}