Coverage Report

Created: 2024-09-08 07:14

/src/libjxl/lib/jpegli/decode_marker.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
2
//
3
// Use of this source code is governed by a BSD-style
4
// license that can be found in the LICENSE file.
5
6
#include "lib/jpegli/decode_marker.h"
7
8
#include <jxl/types.h>
9
#include <string.h>
10
11
#include "lib/jpegli/common.h"
12
#include "lib/jpegli/decode_internal.h"
13
#include "lib/jpegli/error.h"
14
#include "lib/jpegli/huffman.h"
15
#include "lib/jpegli/memory_manager.h"
16
#include "lib/jxl/base/printf_macros.h"
17
18
namespace jpegli {
19
namespace {
20
21
constexpr int kMaxDimPixels = 65535;
22
constexpr uint8_t kIccProfileTag[12] = "ICC_PROFILE";
23
24
// Macros for commonly used error conditions.
25
26
#define JPEG_VERIFY_LEN(n)                               \
27
60.2k
  if (pos + (n) > len) {                                 \
28
38
    JPEGLI_ERROR("Unexpected end of marker: pos=%" PRIuS \
29
38
                 " need=%d len=%" PRIuS,                 \
30
38
                 pos, static_cast<int>(n), len);         \
31
38
  }
32
33
#define JPEG_VERIFY_INPUT(var, low, high)                        \
34
368k
  if ((var) < (low) || (var) > (high)) {                         \
35
500
    JPEGLI_ERROR("Invalid " #var ": %d", static_cast<int>(var)); \
36
500
  }
37
38
#define JPEG_VERIFY_MARKER_END()                                              \
39
15.8k
  if (pos != len) {                                                           \
40
48
    JPEGLI_ERROR("Invalid marker length: declared=%" PRIuS " actual=%" PRIuS, \
41
48
                 len, pos);                                                   \
42
48
  }
43
44
619k
inline int ReadUint8(const uint8_t* data, size_t* pos) {
45
619k
  return data[(*pos)++];
46
619k
}
47
48
25.6k
inline int ReadUint16(const uint8_t* data, size_t* pos) {
49
25.6k
  int v = (data[*pos] << 8) + data[*pos + 1];
50
25.6k
  *pos += 2;
51
25.6k
  return v;
52
25.6k
}
53
54
3.57k
void ProcessSOF(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
55
3.57k
  jpeg_decomp_master* m = cinfo->master;
56
3.57k
  if (!m->found_soi_) {
57
0
    JPEGLI_ERROR("Unexpected SOF marker.");
58
0
  }
59
3.57k
  if (m->found_sof_) {
60
6
    JPEGLI_ERROR("Duplicate SOF marker.");
61
6
  }
62
3.56k
  m->found_sof_ = true;
63
3.56k
  cinfo->progressive_mode = TO_JXL_BOOL(cinfo->unread_marker == 0xc2);
64
3.56k
  cinfo->arith_code = 0;
65
3.56k
  size_t pos = 2;
66
3.56k
  JPEG_VERIFY_LEN(6);
67
3.56k
  cinfo->data_precision = ReadUint8(data, &pos);
68
3.56k
  cinfo->image_height = ReadUint16(data, &pos);
69
3.56k
  cinfo->image_width = ReadUint16(data, &pos);
70
3.56k
  cinfo->num_components = ReadUint8(data, &pos);
71
3.56k
  JPEG_VERIFY_INPUT(cinfo->data_precision, kJpegPrecision, kJpegPrecision);
72
3.54k
  JPEG_VERIFY_INPUT(cinfo->image_height, 1, kMaxDimPixels);
73
3.53k
  JPEG_VERIFY_INPUT(cinfo->image_width, 1, kMaxDimPixels);
74
3.53k
  JPEG_VERIFY_INPUT(cinfo->num_components, 1, kMaxComponents);
75
3.50k
  JPEG_VERIFY_LEN(3 * cinfo->num_components);
76
3.50k
  cinfo->comp_info = jpegli::Allocate<jpeg_component_info>(
77
3.50k
      cinfo, cinfo->num_components, JPOOL_IMAGE);
78
79
  // Read sampling factors and quant table index for each component.
80
3.50k
  uint8_t ids_seen[256] = {0};
81
3.50k
  cinfo->max_h_samp_factor = 1;
82
3.50k
  cinfo->max_v_samp_factor = 1;
83
10.0k
  for (int i = 0; i < cinfo->num_components; ++i) {
84
6.60k
    jpeg_component_info* comp = &cinfo->comp_info[i];
85
6.60k
    comp->component_index = i;
86
6.60k
    const int id = ReadUint8(data, &pos);
87
6.60k
    if (ids_seen[id]) {  // (cf. section B.2.2, syntax of Ci)
88
1
      JPEGLI_ERROR("Duplicate ID %d in SOF.", id);
89
1
    }
90
6.60k
    ids_seen[id] = 1;
91
6.60k
    comp->component_id = id;
92
6.60k
    int factor = ReadUint8(data, &pos);
93
6.60k
    int h_samp_factor = factor >> 4;
94
6.60k
    int v_samp_factor = factor & 0xf;
95
6.60k
    JPEG_VERIFY_INPUT(h_samp_factor, 1, MAX_SAMP_FACTOR);
96
6.57k
    JPEG_VERIFY_INPUT(v_samp_factor, 1, MAX_SAMP_FACTOR);
97
6.56k
    comp->h_samp_factor = h_samp_factor;
98
6.56k
    comp->v_samp_factor = v_samp_factor;
99
6.56k
    cinfo->max_h_samp_factor =
100
6.56k
        std::max(cinfo->max_h_samp_factor, h_samp_factor);
101
6.56k
    cinfo->max_v_samp_factor =
102
6.56k
        std::max(cinfo->max_v_samp_factor, v_samp_factor);
103
6.56k
    int quant_tbl_idx = ReadUint8(data, &pos);
104
6.56k
    JPEG_VERIFY_INPUT(quant_tbl_idx, 0, NUM_QUANT_TBLS - 1);
105
6.55k
    comp->quant_tbl_no = quant_tbl_idx;
106
6.55k
    comp->quant_table = nullptr;  // will be allocated after SOS marker
107
6.55k
  }
108
3.45k
  JPEG_VERIFY_MARKER_END();
109
110
  // Set the input colorspace based on the markers we have seen and set
111
  // default output colorspace.
112
3.43k
  if (cinfo->num_components == 1) {
113
1.79k
    cinfo->jpeg_color_space = JCS_GRAYSCALE;
114
1.79k
    cinfo->out_color_space = JCS_GRAYSCALE;
115
1.79k
  } else if (cinfo->num_components == 3) {
116
586
    if (cinfo->saw_JFIF_marker) {
117
13
      cinfo->jpeg_color_space = JCS_YCbCr;
118
573
    } else if (cinfo->saw_Adobe_marker) {
119
11
      cinfo->jpeg_color_space =
120
11
          cinfo->Adobe_transform == 0 ? JCS_RGB : JCS_YCbCr;
121
562
    } else {
122
562
      cinfo->jpeg_color_space = JCS_YCbCr;
123
562
      if (cinfo->comp_info[0].component_id == 'R' &&  //
124
562
          cinfo->comp_info[1].component_id == 'G' &&  //
125
562
          cinfo->comp_info[2].component_id == 'B') {
126
1
        cinfo->jpeg_color_space = JCS_RGB;
127
1
      }
128
562
    }
129
586
    cinfo->out_color_space = JCS_RGB;
130
1.05k
  } else if (cinfo->num_components == 4) {
131
430
    if (cinfo->saw_Adobe_marker) {
132
67
      cinfo->jpeg_color_space =
133
67
          cinfo->Adobe_transform == 0 ? JCS_CMYK : JCS_YCCK;
134
363
    } else {
135
363
      cinfo->jpeg_color_space = JCS_CMYK;
136
363
    }
137
430
    cinfo->out_color_space = JCS_CMYK;
138
430
  }
139
140
  // We have checked above that none of the sampling factors are 0, so the max
141
  // sampling factors can not be 0.
142
3.43k
  cinfo->total_iMCU_rows =
143
3.43k
      DivCeil(cinfo->image_height, cinfo->max_v_samp_factor * DCTSIZE);
144
3.43k
  m->iMCU_cols_ =
145
3.43k
      DivCeil(cinfo->image_width, cinfo->max_h_samp_factor * DCTSIZE);
146
  // Compute the block dimensions for each component.
147
9.91k
  for (int i = 0; i < cinfo->num_components; ++i) {
148
6.50k
    jpeg_component_info* comp = &cinfo->comp_info[i];
149
6.50k
    if (cinfo->max_h_samp_factor % comp->h_samp_factor != 0 ||
150
6.50k
        cinfo->max_v_samp_factor % comp->v_samp_factor != 0) {
151
28
      JPEGLI_ERROR("Non-integral subsampling ratios.");
152
28
    }
153
6.47k
    m->h_factor[i] = cinfo->max_h_samp_factor / comp->h_samp_factor;
154
6.47k
    m->v_factor[i] = cinfo->max_v_samp_factor / comp->v_samp_factor;
155
6.47k
    comp->downsampled_width = DivCeil(cinfo->image_width, m->h_factor[i]);
156
6.47k
    comp->downsampled_height = DivCeil(cinfo->image_height, m->v_factor[i]);
157
6.47k
    comp->width_in_blocks = DivCeil(comp->downsampled_width, DCTSIZE);
158
6.47k
    comp->height_in_blocks = DivCeil(comp->downsampled_height, DCTSIZE);
159
6.47k
  }
160
3.40k
  memset(m->scan_progression_, 0, sizeof(m->scan_progression_));
161
3.40k
}
162
163
6.86k
void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
164
6.86k
  jpeg_decomp_master* m = cinfo->master;
165
6.86k
  if (!m->found_sof_) {
166
1
    JPEGLI_ERROR("Unexpected SOS marker.");
167
1
  }
168
6.86k
  m->found_sos_ = true;
169
6.86k
  size_t pos = 2;
170
6.86k
  JPEG_VERIFY_LEN(1);
171
6.86k
  cinfo->comps_in_scan = ReadUint8(data, &pos);
172
6.86k
  JPEG_VERIFY_INPUT(cinfo->comps_in_scan, 1, cinfo->num_components);
173
6.83k
  JPEG_VERIFY_INPUT(cinfo->comps_in_scan, 1, MAX_COMPS_IN_SCAN);
174
175
6.83k
  JPEG_VERIFY_LEN(2 * cinfo->comps_in_scan);
176
6.83k
  bool is_interleaved = (cinfo->comps_in_scan > 1);
177
6.83k
  uint8_t ids_seen[256] = {0};
178
6.83k
  cinfo->blocks_in_MCU = 0;
179
15.4k
  for (int i = 0; i < cinfo->comps_in_scan; ++i) {
180
8.74k
    int id = ReadUint8(data, &pos);
181
8.74k
    if (ids_seen[id]) {  // (cf. section B.2.3, regarding CSj)
182
1
      JPEGLI_ERROR("Duplicate ID %d in SOS.", id);
183
1
    }
184
8.74k
    ids_seen[id] = 1;
185
8.74k
    jpeg_component_info* comp = nullptr;
186
30.5k
    for (int j = 0; j < cinfo->num_components; ++j) {
187
21.7k
      if (cinfo->comp_info[j].component_id == id) {
188
8.65k
        comp = &cinfo->comp_info[j];
189
8.65k
        cinfo->cur_comp_info[i] = comp;
190
8.65k
      }
191
21.7k
    }
192
8.74k
    if (!comp) {
193
86
      JPEGLI_ERROR("SOS marker: Could not find component with id %d", id);
194
86
    }
195
8.65k
    int c = ReadUint8(data, &pos);
196
8.65k
    comp->dc_tbl_no = c >> 4;
197
8.65k
    comp->ac_tbl_no = c & 0xf;
198
8.65k
    JPEG_VERIFY_INPUT(comp->dc_tbl_no, 0, 3);
199
8.63k
    JPEG_VERIFY_INPUT(comp->ac_tbl_no, 0, 3);
200
8.63k
    comp->MCU_width = is_interleaved ? comp->h_samp_factor : 1;
201
8.63k
    comp->MCU_height = is_interleaved ? comp->v_samp_factor : 1;
202
8.63k
    comp->MCU_blocks = comp->MCU_width * comp->MCU_height;
203
8.63k
    if (cinfo->blocks_in_MCU + comp->MCU_blocks > D_MAX_BLOCKS_IN_MCU) {
204
2
      JPEGLI_ERROR("Too many blocks in MCU.");
205
2
    }
206
23.5k
    for (int j = 0; j < comp->MCU_blocks; ++j) {
207
14.9k
      cinfo->MCU_membership[cinfo->blocks_in_MCU++] = i;
208
14.9k
    }
209
8.62k
  }
210
6.72k
  JPEG_VERIFY_LEN(3);
211
6.71k
  cinfo->Ss = ReadUint8(data, &pos);
212
6.71k
  cinfo->Se = ReadUint8(data, &pos);
213
6.71k
  JPEG_VERIFY_INPUT(cinfo->Ss, 0, 63);
214
6.69k
  JPEG_VERIFY_INPUT(cinfo->Se, cinfo->Ss, 63);
215
6.67k
  int c = ReadUint8(data, &pos);
216
6.67k
  cinfo->Ah = c >> 4;
217
6.67k
  cinfo->Al = c & 0xf;
218
6.67k
  JPEG_VERIFY_MARKER_END();
219
220
6.66k
  if (cinfo->input_scan_number == 0) {
221
3.21k
    m->is_multiscan_ = (cinfo->comps_in_scan < cinfo->num_components ||
222
3.21k
                        FROM_JXL_BOOL(cinfo->progressive_mode));
223
3.21k
  }
224
6.66k
  if (cinfo->Ah != 0 && cinfo->Al != cinfo->Ah - 1) {
225
    // section G.1.1.1.2 : Successive approximation control only improves
226
    // by one bit at a time.
227
14
    JPEGLI_ERROR("Invalid progressive parameters: Al=%d Ah=%d", cinfo->Al,
228
14
                 cinfo->Ah);
229
14
  }
230
6.64k
  if (!cinfo->progressive_mode) {
231
780
    cinfo->Ss = 0;
232
780
    cinfo->Se = 63;
233
780
    cinfo->Ah = 0;
234
780
    cinfo->Al = 0;
235
780
  }
236
6.64k
  const uint16_t scan_bitmask =
237
6.64k
      cinfo->Ah == 0 ? (0xffff << cinfo->Al) : (1u << cinfo->Al);
238
6.64k
  const uint16_t refinement_bitmask = (1 << cinfo->Al) - 1;
239
6.64k
  if (!cinfo->coef_bits) {
240
3.20k
    cinfo->coef_bits =
241
3.20k
        Allocate<int[DCTSIZE2]>(cinfo, cinfo->num_components * 2, JPOOL_IMAGE);
242
3.20k
    m->coef_bits_latch =
243
3.20k
        Allocate<int[SAVED_COEFS]>(cinfo, cinfo->num_components, JPOOL_IMAGE);
244
3.20k
    m->prev_coef_bits_latch =
245
3.20k
        Allocate<int[SAVED_COEFS]>(cinfo, cinfo->num_components, JPOOL_IMAGE);
246
247
9.29k
    for (int c = 0; c < cinfo->num_components; ++c) {
248
395k
      for (int i = 0; i < DCTSIZE2; ++i) {
249
389k
        cinfo->coef_bits[c][i] = -1;
250
389k
        if (i < SAVED_COEFS) {
251
60.9k
          m->coef_bits_latch[c][i] = -1;
252
60.9k
        }
253
389k
      }
254
6.09k
    }
255
3.20k
  }
256
257
15.1k
  for (int i = 0; i < cinfo->comps_in_scan; ++i) {
258
8.49k
    int comp_idx = cinfo->cur_comp_info[i]->component_index;
259
196k
    for (int k = cinfo->Ss; k <= cinfo->Se; ++k) {
260
187k
      if (m->scan_progression_[comp_idx][k] & scan_bitmask) {
261
23
        JPEGLI_ERROR(
262
23
            "Overlapping scans: component=%d k=%d prev_mask: %u cur_mask %u",
263
23
            comp_idx, k, m->scan_progression_[i][k], scan_bitmask);
264
23
      }
265
187k
      if (m->scan_progression_[comp_idx][k] & refinement_bitmask) {
266
2
        JPEGLI_ERROR(
267
2
            "Invalid scan order, a more refined scan was already done: "
268
2
            "component=%d k=%d prev_mask=%u cur_mask=%u",
269
2
            comp_idx, k, m->scan_progression_[i][k], scan_bitmask);
270
2
      }
271
187k
      m->scan_progression_[comp_idx][k] |= scan_bitmask;
272
187k
    }
273
8.49k
  }
274
6.62k
  if (cinfo->Al > 10) {
275
1
    JPEGLI_ERROR("Scan parameter Al=%d is not supported.", cinfo->Al);
276
1
  }
277
6.62k
}
278
279
// Reads the Define Huffman Table (DHT) marker segment and builds the Huffman
280
// decoding table in either dc_huff_lut_ or ac_huff_lut_, depending on the type
281
// and solt_id of Huffman code being read.
282
2.44k
void ProcessDHT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
283
2.44k
  size_t pos = 2;
284
2.44k
  if (pos == len) {
285
1
    JPEGLI_ERROR("DHT marker: no Huffman table found");
286
1
  }
287
14.5k
  while (pos < len) {
288
12.2k
    JPEG_VERIFY_LEN(1 + kJpegHuffmanMaxBitLength);
289
    // The index of the Huffman code in the current set of Huffman codes. For AC
290
    // component Huffman codes, 0x10 is added to the index.
291
12.2k
    int slot_id = ReadUint8(data, &pos);
292
12.2k
    int huffman_index = slot_id;
293
12.2k
    bool is_ac_table = ((slot_id & 0x10) != 0);
294
12.2k
    JHUFF_TBL** table;
295
12.2k
    if (is_ac_table) {
296
3.23k
      huffman_index -= 0x10;
297
3.23k
      JPEG_VERIFY_INPUT(huffman_index, 0, NUM_HUFF_TBLS - 1);
298
3.13k
      table = &cinfo->ac_huff_tbl_ptrs[huffman_index];
299
9.03k
    } else {
300
9.03k
      JPEG_VERIFY_INPUT(huffman_index, 0, NUM_HUFF_TBLS - 1);
301
9.02k
      table = &cinfo->dc_huff_tbl_ptrs[huffman_index];
302
9.02k
    }
303
12.1k
    if (*table == nullptr) {
304
1.27k
      *table = jpegli_alloc_huff_table(reinterpret_cast<j_common_ptr>(cinfo));
305
1.27k
    }
306
12.1k
    int total_count = 0;
307
206k
    for (size_t i = 1; i <= kJpegHuffmanMaxBitLength; ++i) {
308
194k
      int count = ReadUint8(data, &pos);
309
194k
      (*table)->bits[i] = count;
310
194k
      total_count += count;
311
194k
    }
312
12.1k
    if (is_ac_table) {
313
3.13k
      JPEG_VERIFY_INPUT(total_count, 0, kJpegHuffmanAlphabetSize);
314
9.02k
    } else {
315
      // Allow symbols up to 15 here, we check later whether any invalid symbols
316
      // are actually decoded.
317
      // TODO(szabadka) Make sure decoder works (does not crash) with up to
318
      // 15-nbits DC symbols and then increase kJpegDCAlphabetSize.
319
9.02k
      JPEG_VERIFY_INPUT(total_count, 0, 16);
320
8.99k
    }
321
12.1k
    JPEG_VERIFY_LEN(total_count);
322
112k
    for (int i = 0; i < total_count; ++i) {
323
100k
      int value = ReadUint8(data, &pos);
324
100k
      if (!is_ac_table) {
325
3.10k
        JPEG_VERIFY_INPUT(value, 0, 15);
326
3.08k
      }
327
100k
      (*table)->huffval[i] = value;
328
100k
    }
329
3.00M
    for (int i = total_count; i < kJpegHuffmanAlphabetSize; ++i) {
330
2.99M
      (*table)->huffval[i] = 0;
331
2.99M
    }
332
12.0k
  }
333
2.25k
  JPEG_VERIFY_MARKER_END();
334
2.25k
}
335
336
3.34k
void ProcessDQT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
337
3.34k
  jpeg_decomp_master* m = cinfo->master;
338
3.34k
  if (m->found_sos_) {
339
8
    JPEGLI_ERROR("Updating quant tables between scans is not supported.");
340
8
  }
341
3.33k
  size_t pos = 2;
342
3.33k
  if (pos == len) {
343
1
    JPEGLI_ERROR("DQT marker: no quantization table found");
344
1
  }
345
7.31k
  while (pos < len) {
346
4.10k
    JPEG_VERIFY_LEN(1);
347
4.10k
    int quant_table_index = ReadUint8(data, &pos);
348
4.10k
    int precision = quant_table_index >> 4;
349
4.10k
    JPEG_VERIFY_INPUT(precision, 0, 1);
350
4.01k
    quant_table_index &= 0xf;
351
4.01k
    JPEG_VERIFY_INPUT(quant_table_index, 0, NUM_QUANT_TBLS - 1);
352
4.00k
    JPEG_VERIFY_LEN((precision + 1) * DCTSIZE2);
353
354
4.00k
    if (cinfo->quant_tbl_ptrs[quant_table_index] == nullptr) {
355
3.21k
      cinfo->quant_tbl_ptrs[quant_table_index] =
356
3.21k
          jpegli_alloc_quant_table(reinterpret_cast<j_common_ptr>(cinfo));
357
3.21k
    }
358
4.00k
    JQUANT_TBL* quant_table = cinfo->quant_tbl_ptrs[quant_table_index];
359
360
258k
    for (size_t i = 0; i < DCTSIZE2; ++i) {
361
254k
      int quant_val =
362
254k
          precision ? ReadUint16(data, &pos) : ReadUint8(data, &pos);
363
254k
      JPEG_VERIFY_INPUT(quant_val, 1, 65535);
364
254k
      quant_table->quantval[kJPEGNaturalOrder[i]] = quant_val;
365
254k
    }
366
4.00k
  }
367
3.20k
  JPEG_VERIFY_MARKER_END();
368
3.20k
}
369
370
5
void ProcessDNL(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
371
  // Ignore marker.
372
5
}
373
374
294
void ProcessDRI(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
375
294
  jpeg_decomp_master* m = cinfo->master;
376
294
  if (m->found_dri_) {
377
1
    JPEGLI_ERROR("Duplicate DRI marker.");
378
1
  }
379
293
  m->found_dri_ = true;
380
293
  size_t pos = 2;
381
293
  JPEG_VERIFY_LEN(2);
382
291
  cinfo->restart_interval = ReadUint16(data, &pos);
383
291
  JPEG_VERIFY_MARKER_END();
384
275
}
385
386
11.3k
void ProcessAPP(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
387
11.3k
  jpeg_decomp_master* m = cinfo->master;
388
11.3k
  const uint8_t marker = cinfo->unread_marker;
389
11.3k
  const uint8_t* payload = data + 2;
390
11.3k
  size_t payload_size = len - 2;
391
11.3k
  if (marker == 0xE0) {
392
740
    if (payload_size >= 14 && memcmp(payload, "JFIF", 4) == 0) {
393
259
      cinfo->saw_JFIF_marker = TRUE;
394
259
      cinfo->JFIF_major_version = payload[5];
395
259
      cinfo->JFIF_minor_version = payload[6];
396
259
      cinfo->density_unit = payload[7];
397
259
      cinfo->X_density = (payload[8] << 8) + payload[9];
398
259
      cinfo->Y_density = (payload[10] << 8) + payload[11];
399
259
    }
400
10.5k
  } else if (marker == 0xEE) {
401
8.83k
    if (payload_size >= 12 && memcmp(payload, "Adobe", 5) == 0) {
402
287
      cinfo->saw_Adobe_marker = TRUE;
403
287
      cinfo->Adobe_transform = payload[11];
404
287
    }
405
8.83k
  } else if (marker == 0xE2) {
406
1.17k
    if (payload_size >= sizeof(kIccProfileTag) &&
407
1.17k
        memcmp(payload, kIccProfileTag, sizeof(kIccProfileTag)) == 0) {
408
98
      payload += sizeof(kIccProfileTag);
409
98
      payload_size -= sizeof(kIccProfileTag);
410
98
      if (payload_size < 2) {
411
1
        JPEGLI_ERROR("ICC chunk is too small.");
412
1
      }
413
97
      uint8_t index = payload[0];
414
97
      uint8_t total = payload[1];
415
97
      ++m->icc_index_;
416
97
      if (m->icc_index_ != index) {
417
10
        JPEGLI_ERROR("Invalid ICC chunk order.");
418
10
      }
419
87
      if (total == 0) {
420
1
        JPEGLI_ERROR("Invalid ICC chunk total.");
421
1
      }
422
86
      if (m->icc_total_ == 0) {
423
54
        m->icc_total_ = total;
424
54
      } else if (m->icc_total_ != total) {
425
14
        JPEGLI_ERROR("Invalid ICC chunk total.");
426
14
      }
427
72
      if (m->icc_index_ > m->icc_total_) {
428
1
        JPEGLI_ERROR("Invalid ICC chunk index.");
429
1
      }
430
71
      m->icc_profile_.insert(m->icc_profile_.end(), payload + 2,
431
71
                             payload + payload_size);
432
71
    }
433
1.17k
  }
434
11.3k
}
435
436
520
void ProcessCOM(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
437
  // Ignore marker.
438
520
}
439
440
4.37k
void ProcessSOI(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
441
4.37k
  jpeg_decomp_master* m = cinfo->master;
442
4.37k
  if (m->found_soi_) {
443
37
    JPEGLI_ERROR("Duplicate SOI marker");
444
37
  }
445
4.33k
  m->found_soi_ = true;
446
4.33k
}
447
448
2.94k
void ProcessEOI(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
449
2.94k
  cinfo->master->found_eoi_ = true;
450
2.94k
}
451
452
0
void SaveMarker(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
453
0
  const uint8_t marker = cinfo->unread_marker;
454
0
  const uint8_t* payload = data + 2;
455
0
  size_t payload_size = len - 2;
456
457
  // Insert new saved marker to the head of the list.
458
0
  jpeg_saved_marker_ptr next = cinfo->marker_list;
459
0
  cinfo->marker_list =
460
0
      jpegli::Allocate<jpeg_marker_struct>(cinfo, 1, JPOOL_IMAGE);
461
0
  cinfo->marker_list->next = next;
462
0
  cinfo->marker_list->marker = marker;
463
0
  cinfo->marker_list->original_length = payload_size;
464
0
  cinfo->marker_list->data_length = payload_size;
465
0
  cinfo->marker_list->data =
466
0
      jpegli::Allocate<uint8_t>(cinfo, payload_size, JPOOL_IMAGE);
467
0
  memcpy(cinfo->marker_list->data, payload, payload_size);
468
0
}
469
470
uint8_t ProcessNextMarker(j_decompress_ptr cinfo, const uint8_t* const data,
471
17.1M
                          const size_t len, size_t* pos) {
472
17.1M
  jpeg_decomp_master* m = cinfo->master;
473
17.1M
  size_t num_skipped = 0;
474
17.1M
  uint8_t marker = cinfo->unread_marker;
475
17.1M
  if (marker == 0) {
476
    // kIsValidMarker[i] == 1 means (0xc0 + i) is a valid marker.
477
305k
    static const uint8_t kIsValidMarker[] = {
478
305k
        1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
479
305k
        1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
480
305k
        1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
481
305k
    };
482
    // Skip bytes between markers.
483
20.8M
    while (*pos + 1 < len && (data[*pos] != 0xff || data[*pos + 1] < 0xc0 ||
484
20.5M
                              !kIsValidMarker[data[*pos + 1] - 0xc0])) {
485
20.5M
      ++(*pos);
486
20.5M
      ++num_skipped;
487
20.5M
    }
488
305k
    if (*pos + 2 > len) {
489
270k
      return kNeedMoreInput;
490
270k
    }
491
35.6k
    marker = data[*pos + 1];
492
35.6k
    if (num_skipped > 0) {
493
7.58k
      if (m->found_soi_) {
494
7.49k
        JPEGLI_WARN("Skipped %d bytes before marker 0x%02x",
495
7.49k
                    static_cast<int>(num_skipped), marker);
496
7.49k
      } else {
497
83
        JPEGLI_ERROR("Did not find SOI marker.");
498
83
      }
499
7.58k
    }
500
35.5k
    *pos += 2;
501
35.5k
    cinfo->unread_marker = marker;
502
35.5k
  }
503
16.9M
  if (!m->found_soi_ && marker != 0xd8) {
504
13
    JPEGLI_ERROR("Did not find SOI marker.");
505
13
  }
506
16.9M
  if (GetMarkerProcessor(cinfo)) {
507
0
    return kHandleMarkerProcessor;
508
0
  }
509
16.9M
  const uint8_t* marker_data = &data[*pos];
510
16.9M
  size_t marker_len = 0;
511
16.9M
  if (marker != 0xd8 && marker != 0xd9) {
512
16.9M
    if (*pos + 2 > len) {
513
8.54k
      return kNeedMoreInput;
514
8.54k
    }
515
16.8M
    marker_len += (data[*pos] << 8) + data[*pos + 1];
516
16.8M
    if (marker_len < 2) {
517
5
      JPEGLI_ERROR("Invalid marker length");
518
5
    }
519
16.8M
    if (*pos + marker_len > len) {
520
      // TODO(szabadka) Limit our memory usage by using the skip_input_data
521
      // source manager callback on APP markers that are not saved.
522
16.8M
      return kNeedMoreInput;
523
16.8M
    }
524
28.4k
    if (marker >= 0xe0 && m->markers_to_save_[marker - 0xe0]) {
525
0
      SaveMarker(cinfo, marker_data, marker_len);
526
0
    }
527
28.4k
  }
528
35.7k
  if (marker == 0xc0 || marker == 0xc1 || marker == 0xc2) {
529
3.57k
    ProcessSOF(cinfo, marker_data, marker_len);
530
32.1k
  } else if (marker == 0xc4) {
531
2.44k
    ProcessDHT(cinfo, marker_data, marker_len);
532
29.7k
  } else if (marker == 0xda) {
533
6.86k
    ProcessSOS(cinfo, marker_data, marker_len);
534
22.8k
  } else if (marker == 0xdb) {
535
3.34k
    ProcessDQT(cinfo, marker_data, marker_len);
536
19.5k
  } else if (marker == 0xdc) {
537
5
    ProcessDNL(cinfo, marker_data, marker_len);
538
19.5k
  } else if (marker == 0xdd) {
539
294
    ProcessDRI(cinfo, marker_data, marker_len);
540
19.2k
  } else if (marker >= 0xe0 && marker <= 0xef) {
541
11.3k
    ProcessAPP(cinfo, marker_data, marker_len);
542
11.3k
  } else if (marker == 0xfe) {
543
520
    ProcessCOM(cinfo, marker_data, marker_len);
544
7.40k
  } else if (marker == 0xd8) {
545
4.37k
    ProcessSOI(cinfo, marker_data, marker_len);
546
4.37k
  } else if (marker == 0xd9) {
547
2.94k
    ProcessEOI(cinfo, marker_data, marker_len);
548
2.94k
  } else {
549
88
    JPEGLI_ERROR("Unexpected marker 0x%x", marker);
550
88
  }
551
35.6k
  *pos += marker_len;
552
35.6k
  cinfo->unread_marker = 0;
553
35.6k
  if (marker == 0xda) {
554
6.62k
    return JPEG_REACHED_SOS;
555
29.0k
  } else if (marker == 0xd9) {
556
2.94k
    return JPEG_REACHED_EOI;
557
2.94k
  }
558
26.1k
  return kProcessNextMarker;
559
35.6k
}
560
561
}  // namespace
562
563
16.9M
jpeg_marker_parser_method GetMarkerProcessor(j_decompress_ptr cinfo) {
564
16.9M
  jpeg_decomp_master* m = cinfo->master;
565
16.9M
  uint8_t marker = cinfo->unread_marker;
566
16.9M
  jpeg_marker_parser_method callback = nullptr;
567
16.9M
  if (marker >= 0xe0 && marker <= 0xef) {
568
5.61M
    callback = m->app_marker_parsers[marker - 0xe0];
569
11.2M
  } else if (marker == 0xfe) {
570
1.09M
    callback = m->com_marker_parser;
571
1.09M
  }
572
16.9M
  return callback;
573
16.9M
}
574
575
int ProcessMarkers(j_decompress_ptr cinfo, const uint8_t* const data,
576
17.1M
                   const size_t len, size_t* pos) {
577
17.1M
  for (;;) {
578
17.1M
    int status = ProcessNextMarker(cinfo, data, len, pos);
579
17.1M
    if (status != kProcessNextMarker) {
580
17.1M
      return status;
581
17.1M
    }
582
17.1M
  }
583
17.1M
}
584
585
}  // namespace jpegli