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/jxl/jpeg/enc_jpeg_data_reader.h"
7 
8 #include <inttypes.h>
9 #include <string.h>
10 
11 #include <algorithm>
12 #include <string>
13 #include <vector>
14 
15 #include "lib/jxl/base/status.h"
16 #include "lib/jxl/common.h"
17 #include "lib/jxl/jpeg/enc_jpeg_huffman_decode.h"
18 #include "lib/jxl/jpeg/jpeg_data.h"
19 
20 // By default only print debug messages when JXL_DEBUG_ON_ERROR is enabled.
21 #ifndef JXL_DEBUG_JPEG_DATA_READER
22 #define JXL_DEBUG_JPEG_DATA_READER JXL_DEBUG_ON_ERROR
23 #endif  // JXL_DEBUG_JPEG_DATA_READER
24 
25 #define JXL_JPEG_DEBUG(format, ...) \
26   JXL_DEBUG(JXL_DEBUG_JPEG_DATA_READER, format, ##__VA_ARGS__)
27 
28 namespace jxl {
29 namespace jpeg {
30 
31 namespace {
32 static const int kBrunsliMaxSampling = 15;
33 static const size_t kBrunsliMaxNumBlocks = 1ull << 24;
34 
35 // Macros for commonly used error conditions.
36 
37 #define JXL_JPEG_VERIFY_LEN(n)                                               \
38   if (*pos + (n) > len) {                                                    \
39     JXL_JPEG_DEBUG("Unexpected end of input: pos=%zu need=%d len=%zu", *pos, \
40                    static_cast<int>(n), len);                                \
41     jpg->error = JPEGReadError::UNEXPECTED_EOF;                              \
42     return false;                                                            \
43   }
44 
45 #define JXL_JPEG_VERIFY_INPUT(var, low, high, code)                \
46   if ((var) < (low) || (var) > (high)) {                           \
47     JXL_JPEG_DEBUG("Invalid " #var ": %d", static_cast<int>(var)); \
48     jpg->error = JPEGReadError::INVALID_##code;                    \
49     return false;                                                  \
50   }
51 
52 #define JXL_JPEG_VERIFY_MARKER_END()                                 \
53   if (start_pos + marker_len != *pos) {                              \
54     JXL_JPEG_DEBUG("Invalid marker length: declared=%zu actual=%zu", \
55                    marker_len, (*pos - start_pos));                  \
56     jpg->error = JPEGReadError::WRONG_MARKER_SIZE;                   \
57     return false;                                                    \
58   }
59 
60 #define JXL_JPEG_EXPECT_MARKER()                                      \
61   if (pos + 2 > len || data[pos] != 0xff) {                           \
62     JXL_JPEG_DEBUG(                                                   \
63         "Marker byte (0xff) expected, found: 0x%.2x pos=%zu len=%zu", \
64         (pos < len ? data[pos] : 0), pos, len);                       \
65     jpg->error = JPEGReadError::MARKER_BYTE_NOT_FOUND;                \
66     return false;                                                     \
67   }
68 
ReadUint8(const uint8_t * data,size_t * pos)69 inline int ReadUint8(const uint8_t* data, size_t* pos) {
70   return data[(*pos)++];
71 }
72 
ReadUint16(const uint8_t * data,size_t * pos)73 inline int ReadUint16(const uint8_t* data, size_t* pos) {
74   int v = (data[*pos] << 8) + data[*pos + 1];
75   *pos += 2;
76   return v;
77 }
78 
79 // Reads the Start of Frame (SOF) marker segment and fills in *jpg with the
80 // parsed data.
ProcessSOF(const uint8_t * data,const size_t len,JpegReadMode mode,size_t * pos,JPEGData * jpg)81 bool ProcessSOF(const uint8_t* data, const size_t len, JpegReadMode mode,
82                 size_t* pos, JPEGData* jpg) {
83   if (jpg->width != 0) {
84     JXL_JPEG_DEBUG("Duplicate SOF marker.");
85     jpg->error = JPEGReadError::DUPLICATE_SOF;
86     return false;
87   }
88   const size_t start_pos = *pos;
89   JXL_JPEG_VERIFY_LEN(8);
90   size_t marker_len = ReadUint16(data, pos);
91   int precision = ReadUint8(data, pos);
92   int height = ReadUint16(data, pos);
93   int width = ReadUint16(data, pos);
94   int num_components = ReadUint8(data, pos);
95   JXL_JPEG_VERIFY_INPUT(precision, 8, 8, PRECISION);
96   JXL_JPEG_VERIFY_INPUT(height, 1, kMaxDimPixels, HEIGHT);
97   JXL_JPEG_VERIFY_INPUT(width, 1, kMaxDimPixels, WIDTH);
98   JXL_JPEG_VERIFY_INPUT(num_components, 1, kMaxComponents, NUMCOMP);
99   JXL_JPEG_VERIFY_LEN(3 * num_components);
100   jpg->height = height;
101   jpg->width = width;
102   jpg->components.resize(num_components);
103 
104   // Read sampling factors and quant table index for each component.
105   std::vector<bool> ids_seen(256, false);
106   int max_h_samp_factor = 1;
107   int max_v_samp_factor = 1;
108   for (size_t i = 0; i < jpg->components.size(); ++i) {
109     const int id = ReadUint8(data, pos);
110     if (ids_seen[id]) {  // (cf. section B.2.2, syntax of Ci)
111       JXL_JPEG_DEBUG("Duplicate ID %d in SOF.", id);
112       jpg->error = JPEGReadError::DUPLICATE_COMPONENT_ID;
113       return false;
114     }
115     ids_seen[id] = true;
116     jpg->components[i].id = id;
117     int factor = ReadUint8(data, pos);
118     int h_samp_factor = factor >> 4;
119     int v_samp_factor = factor & 0xf;
120     JXL_JPEG_VERIFY_INPUT(h_samp_factor, 1, kBrunsliMaxSampling, SAMP_FACTOR);
121     JXL_JPEG_VERIFY_INPUT(v_samp_factor, 1, kBrunsliMaxSampling, SAMP_FACTOR);
122     jpg->components[i].h_samp_factor = h_samp_factor;
123     jpg->components[i].v_samp_factor = v_samp_factor;
124     jpg->components[i].quant_idx = ReadUint8(data, pos);
125     max_h_samp_factor = std::max(max_h_samp_factor, h_samp_factor);
126     max_v_samp_factor = std::max(max_v_samp_factor, v_samp_factor);
127   }
128 
129   // We have checked above that none of the sampling factors are 0, so the max
130   // sampling factors can not be 0.
131   int MCU_rows = DivCeil(jpg->height, max_v_samp_factor * 8);
132   int MCU_cols = DivCeil(jpg->width, max_h_samp_factor * 8);
133   // Compute the block dimensions for each component.
134   for (size_t i = 0; i < jpg->components.size(); ++i) {
135     JPEGComponent* c = &jpg->components[i];
136     if (max_h_samp_factor % c->h_samp_factor != 0 ||
137         max_v_samp_factor % c->v_samp_factor != 0) {
138       JXL_JPEG_DEBUG("Non-integral subsampling ratios.");
139       jpg->error = JPEGReadError::INVALID_SAMPLING_FACTORS;
140       return false;
141     }
142     c->width_in_blocks = MCU_cols * c->h_samp_factor;
143     c->height_in_blocks = MCU_rows * c->v_samp_factor;
144     const uint64_t num_blocks =
145         static_cast<uint64_t>(c->width_in_blocks) * c->height_in_blocks;
146     if (num_blocks > kBrunsliMaxNumBlocks) {
147       JXL_JPEG_DEBUG("Image too large.");
148       jpg->error = JPEGReadError::IMAGE_TOO_LARGE;
149       return false;
150     }
151     if (mode == JpegReadMode::kReadAll) {
152       c->coeffs.resize(num_blocks * kDCTBlockSize);
153     }
154   }
155   JXL_JPEG_VERIFY_MARKER_END();
156   return true;
157 }
158 
159 // Reads the Start of Scan (SOS) marker segment and fills in *scan_info with the
160 // parsed data.
ProcessSOS(const uint8_t * data,const size_t len,size_t * pos,JPEGData * jpg)161 bool ProcessSOS(const uint8_t* data, const size_t len, size_t* pos,
162                 JPEGData* jpg) {
163   const size_t start_pos = *pos;
164   JXL_JPEG_VERIFY_LEN(3);
165   size_t marker_len = ReadUint16(data, pos);
166   size_t comps_in_scan = ReadUint8(data, pos);
167   JXL_JPEG_VERIFY_INPUT(comps_in_scan, 1, jpg->components.size(),
168                         COMPS_IN_SCAN);
169 
170   JPEGScanInfo scan_info;
171   scan_info.num_components = comps_in_scan;
172   JXL_JPEG_VERIFY_LEN(2 * comps_in_scan);
173   std::vector<bool> ids_seen(256, false);
174   for (size_t i = 0; i < comps_in_scan; ++i) {
175     uint32_t id = ReadUint8(data, pos);
176     if (ids_seen[id]) {  // (cf. section B.2.3, regarding CSj)
177       JXL_JPEG_DEBUG("Duplicate ID %d in SOS.", id);
178       jpg->error = JPEGReadError::DUPLICATE_COMPONENT_ID;
179       return false;
180     }
181     ids_seen[id] = true;
182     bool found_index = false;
183     for (size_t j = 0; j < jpg->components.size(); ++j) {
184       if (jpg->components[j].id == id) {
185         scan_info.components[i].comp_idx = j;
186         found_index = true;
187       }
188     }
189     if (!found_index) {
190       JXL_JPEG_DEBUG("SOS marker: Could not find component with id %d", id);
191       jpg->error = JPEGReadError::COMPONENT_NOT_FOUND;
192       return false;
193     }
194     int c = ReadUint8(data, pos);
195     int dc_tbl_idx = c >> 4;
196     int ac_tbl_idx = c & 0xf;
197     JXL_JPEG_VERIFY_INPUT(dc_tbl_idx, 0, 3, HUFFMAN_INDEX);
198     JXL_JPEG_VERIFY_INPUT(ac_tbl_idx, 0, 3, HUFFMAN_INDEX);
199     scan_info.components[i].dc_tbl_idx = dc_tbl_idx;
200     scan_info.components[i].ac_tbl_idx = ac_tbl_idx;
201   }
202   JXL_JPEG_VERIFY_LEN(3);
203   scan_info.Ss = ReadUint8(data, pos);
204   scan_info.Se = ReadUint8(data, pos);
205   JXL_JPEG_VERIFY_INPUT(static_cast<int>(scan_info.Ss), 0, 63, START_OF_SCAN);
206   JXL_JPEG_VERIFY_INPUT(scan_info.Se, scan_info.Ss, 63, END_OF_SCAN);
207   int c = ReadUint8(data, pos);
208   scan_info.Ah = c >> 4;
209   scan_info.Al = c & 0xf;
210   if (scan_info.Ah != 0 && scan_info.Al != scan_info.Ah - 1) {
211     // section G.1.1.1.2 : Successive approximation control only improves
212     // by one bit at a time. But it's not always respected, so we just issue
213     // a warning.
214     JXL_WARNING("Invalid progressive parameters: Al=%d Ah=%d", scan_info.Al,
215                 scan_info.Ah);
216   }
217   // Check that all the Huffman tables needed for this scan are defined.
218   for (size_t i = 0; i < comps_in_scan; ++i) {
219     bool found_dc_table = false;
220     bool found_ac_table = false;
221     for (size_t j = 0; j < jpg->huffman_code.size(); ++j) {
222       uint32_t slot_id = jpg->huffman_code[j].slot_id;
223       if (slot_id == scan_info.components[i].dc_tbl_idx) {
224         found_dc_table = true;
225       } else if (slot_id == scan_info.components[i].ac_tbl_idx + 16) {
226         found_ac_table = true;
227       }
228     }
229     if (scan_info.Ss == 0 && !found_dc_table) {
230       JXL_JPEG_DEBUG(
231           "SOS marker: Could not find DC Huffman table with index %d",
232           scan_info.components[i].dc_tbl_idx);
233       jpg->error = JPEGReadError::HUFFMAN_TABLE_NOT_FOUND;
234       return false;
235     }
236     if (scan_info.Se > 0 && !found_ac_table) {
237       JXL_JPEG_DEBUG(
238           "SOS marker: Could not find AC Huffman table with index %d",
239           scan_info.components[i].ac_tbl_idx);
240       jpg->error = JPEGReadError::HUFFMAN_TABLE_NOT_FOUND;
241       return false;
242     }
243   }
244   jpg->scan_info.push_back(scan_info);
245   JXL_JPEG_VERIFY_MARKER_END();
246   return true;
247 }
248 
249 // Reads the Define Huffman Table (DHT) marker segment and fills in *jpg with
250 // the parsed data. Builds the Huffman decoding table in either dc_huff_lut or
251 // ac_huff_lut, depending on the type and solt_id of Huffman code being read.
ProcessDHT(const uint8_t * data,const size_t len,JpegReadMode mode,std::vector<HuffmanTableEntry> * dc_huff_lut,std::vector<HuffmanTableEntry> * ac_huff_lut,size_t * pos,JPEGData * jpg)252 bool ProcessDHT(const uint8_t* data, const size_t len, JpegReadMode mode,
253                 std::vector<HuffmanTableEntry>* dc_huff_lut,
254                 std::vector<HuffmanTableEntry>* ac_huff_lut, size_t* pos,
255                 JPEGData* jpg) {
256   const size_t start_pos = *pos;
257   JXL_JPEG_VERIFY_LEN(2);
258   size_t marker_len = ReadUint16(data, pos);
259   if (marker_len == 2) {
260     JXL_JPEG_DEBUG("DHT marker: no Huffman table found");
261     jpg->error = JPEGReadError::EMPTY_DHT;
262     return false;
263   }
264   while (*pos < start_pos + marker_len) {
265     JXL_JPEG_VERIFY_LEN(1 + kJpegHuffmanMaxBitLength);
266     JPEGHuffmanCode huff;
267     huff.slot_id = ReadUint8(data, pos);
268     int huffman_index = huff.slot_id;
269     int is_ac_table = (huff.slot_id & 0x10) != 0;
270     HuffmanTableEntry* huff_lut;
271     if (is_ac_table) {
272       huffman_index -= 0x10;
273       JXL_JPEG_VERIFY_INPUT(huffman_index, 0, 3, HUFFMAN_INDEX);
274       huff_lut = &(*ac_huff_lut)[huffman_index * kJpegHuffmanLutSize];
275     } else {
276       JXL_JPEG_VERIFY_INPUT(huffman_index, 0, 3, HUFFMAN_INDEX);
277       huff_lut = &(*dc_huff_lut)[huffman_index * kJpegHuffmanLutSize];
278     }
279     huff.counts[0] = 0;
280     int total_count = 0;
281     int space = 1 << kJpegHuffmanMaxBitLength;
282     int max_depth = 1;
283     for (size_t i = 1; i <= kJpegHuffmanMaxBitLength; ++i) {
284       int count = ReadUint8(data, pos);
285       if (count != 0) {
286         max_depth = i;
287       }
288       huff.counts[i] = count;
289       total_count += count;
290       space -= count * (1 << (kJpegHuffmanMaxBitLength - i));
291     }
292     if (is_ac_table) {
293       JXL_JPEG_VERIFY_INPUT(total_count, 0, kJpegHuffmanAlphabetSize,
294                             HUFFMAN_CODE);
295     } else {
296       JXL_JPEG_VERIFY_INPUT(total_count, 0, kJpegDCAlphabetSize, HUFFMAN_CODE);
297     }
298     JXL_JPEG_VERIFY_LEN(total_count);
299     std::vector<bool> values_seen(256, false);
300     for (int i = 0; i < total_count; ++i) {
301       int value = ReadUint8(data, pos);
302       if (!is_ac_table) {
303         JXL_JPEG_VERIFY_INPUT(value, 0, kJpegDCAlphabetSize - 1, HUFFMAN_CODE);
304       }
305       if (values_seen[value]) {
306         JXL_JPEG_DEBUG("Duplicate Huffman code value %d", value);
307         jpg->error = JPEGReadError::INVALID_HUFFMAN_CODE;
308         return false;
309       }
310       values_seen[value] = true;
311       huff.values[i] = value;
312     }
313     // Add an invalid symbol that will have the all 1 code.
314     ++huff.counts[max_depth];
315     huff.values[total_count] = kJpegHuffmanAlphabetSize;
316     space -= (1 << (kJpegHuffmanMaxBitLength - max_depth));
317     if (space < 0) {
318       JXL_JPEG_DEBUG("Invalid Huffman code lengths.");
319       jpg->error = JPEGReadError::INVALID_HUFFMAN_CODE;
320       return false;
321     } else if (space > 0 && huff_lut[0].value != 0xffff) {
322       // Re-initialize the values to an invalid symbol so that we can recognize
323       // it when reading the bit stream using a Huffman code with space > 0.
324       for (int i = 0; i < kJpegHuffmanLutSize; ++i) {
325         huff_lut[i].bits = 0;
326         huff_lut[i].value = 0xffff;
327       }
328     }
329     huff.is_last = (*pos == start_pos + marker_len);
330     if (mode == JpegReadMode::kReadAll) {
331       BuildJpegHuffmanTable(&huff.counts[0], &huff.values[0], huff_lut);
332     }
333     jpg->huffman_code.push_back(huff);
334   }
335   JXL_JPEG_VERIFY_MARKER_END();
336   return true;
337 }
338 
339 // Reads the Define Quantization Table (DQT) marker segment and fills in *jpg
340 // with the parsed data.
ProcessDQT(const uint8_t * data,const size_t len,size_t * pos,JPEGData * jpg)341 bool ProcessDQT(const uint8_t* data, const size_t len, size_t* pos,
342                 JPEGData* jpg) {
343   const size_t start_pos = *pos;
344   JXL_JPEG_VERIFY_LEN(2);
345   size_t marker_len = ReadUint16(data, pos);
346   if (marker_len == 2) {
347     JXL_JPEG_DEBUG("DQT marker: no quantization table found");
348     jpg->error = JPEGReadError::EMPTY_DQT;
349     return false;
350   }
351   while (*pos < start_pos + marker_len && jpg->quant.size() < kMaxQuantTables) {
352     JXL_JPEG_VERIFY_LEN(1);
353     int quant_table_index = ReadUint8(data, pos);
354     int quant_table_precision = quant_table_index >> 4;
355     JXL_JPEG_VERIFY_INPUT(quant_table_precision, 0, 1, QUANT_TBL_PRECISION);
356     quant_table_index &= 0xf;
357     JXL_JPEG_VERIFY_INPUT(quant_table_index, 0, 3, QUANT_TBL_INDEX);
358     JXL_JPEG_VERIFY_LEN((quant_table_precision + 1) * kDCTBlockSize);
359     JPEGQuantTable table;
360     table.index = quant_table_index;
361     table.precision = quant_table_precision;
362     for (size_t i = 0; i < kDCTBlockSize; ++i) {
363       int quant_val =
364           quant_table_precision ? ReadUint16(data, pos) : ReadUint8(data, pos);
365       JXL_JPEG_VERIFY_INPUT(quant_val, 1, 65535, QUANT_VAL);
366       table.values[kJPEGNaturalOrder[i]] = quant_val;
367     }
368     table.is_last = (*pos == start_pos + marker_len);
369     jpg->quant.push_back(table);
370   }
371   JXL_JPEG_VERIFY_MARKER_END();
372   return true;
373 }
374 
375 // Reads the DRI marker and saves the restart interval into *jpg.
ProcessDRI(const uint8_t * data,const size_t len,size_t * pos,bool * found_dri,JPEGData * jpg)376 bool ProcessDRI(const uint8_t* data, const size_t len, size_t* pos,
377                 bool* found_dri, JPEGData* jpg) {
378   if (*found_dri) {
379     JXL_JPEG_DEBUG("Duplicate DRI marker.");
380     jpg->error = JPEGReadError::DUPLICATE_DRI;
381     return false;
382   }
383   *found_dri = true;
384   const size_t start_pos = *pos;
385   JXL_JPEG_VERIFY_LEN(4);
386   size_t marker_len = ReadUint16(data, pos);
387   int restart_interval = ReadUint16(data, pos);
388   jpg->restart_interval = restart_interval;
389   JXL_JPEG_VERIFY_MARKER_END();
390   return true;
391 }
392 
393 // Saves the APP marker segment as a string to *jpg.
ProcessAPP(const uint8_t * data,const size_t len,size_t * pos,JPEGData * jpg)394 bool ProcessAPP(const uint8_t* data, const size_t len, size_t* pos,
395                 JPEGData* jpg) {
396   JXL_JPEG_VERIFY_LEN(2);
397   size_t marker_len = ReadUint16(data, pos);
398   JXL_JPEG_VERIFY_INPUT(marker_len, 2, 65535, MARKER_LEN);
399   JXL_JPEG_VERIFY_LEN(marker_len - 2);
400   JXL_DASSERT(*pos >= 3);
401   // Save the marker type together with the app data.
402   const uint8_t* app_str_start = data + *pos - 3;
403   std::vector<uint8_t> app_str(app_str_start, app_str_start + marker_len + 1);
404   *pos += marker_len - 2;
405   jpg->app_data.push_back(app_str);
406   return true;
407 }
408 
409 // Saves the COM marker segment as a string to *jpg.
ProcessCOM(const uint8_t * data,const size_t len,size_t * pos,JPEGData * jpg)410 bool ProcessCOM(const uint8_t* data, const size_t len, size_t* pos,
411                 JPEGData* jpg) {
412   JXL_JPEG_VERIFY_LEN(2);
413   size_t marker_len = ReadUint16(data, pos);
414   JXL_JPEG_VERIFY_INPUT(marker_len, 2, 65535, MARKER_LEN);
415   JXL_JPEG_VERIFY_LEN(marker_len - 2);
416   const uint8_t* com_str_start = data + *pos - 3;
417   std::vector<uint8_t> com_str(com_str_start, com_str_start + marker_len + 1);
418   *pos += marker_len - 2;
419   jpg->com_data.push_back(com_str);
420   return true;
421 }
422 
423 // Helper structure to read bits from the entropy coded data segment.
424 struct BitReaderState {
BitReaderStatejxl::jpeg::__anon59df6e1c0111::BitReaderState425   BitReaderState(const uint8_t* data, const size_t len, size_t pos)
426       : data_(data), len_(len) {
427     Reset(pos);
428   }
429 
Resetjxl::jpeg::__anon59df6e1c0111::BitReaderState430   void Reset(size_t pos) {
431     pos_ = pos;
432     val_ = 0;
433     bits_left_ = 0;
434     next_marker_pos_ = len_ - 2;
435     FillBitWindow();
436   }
437 
438   // Returns the next byte and skips the 0xff/0x00 escape sequences.
GetNextBytejxl::jpeg::__anon59df6e1c0111::BitReaderState439   uint8_t GetNextByte() {
440     if (pos_ >= next_marker_pos_) {
441       ++pos_;
442       return 0;
443     }
444     uint8_t c = data_[pos_++];
445     if (c == 0xff) {
446       uint8_t escape = data_[pos_];
447       if (escape == 0) {
448         ++pos_;
449       } else {
450         // 0xff was followed by a non-zero byte, which means that we found the
451         // start of the next marker segment.
452         next_marker_pos_ = pos_ - 1;
453       }
454     }
455     return c;
456   }
457 
FillBitWindowjxl::jpeg::__anon59df6e1c0111::BitReaderState458   void FillBitWindow() {
459     if (bits_left_ <= 16) {
460       while (bits_left_ <= 56) {
461         val_ <<= 8;
462         val_ |= (uint64_t)GetNextByte();
463         bits_left_ += 8;
464       }
465     }
466   }
467 
ReadBitsjxl::jpeg::__anon59df6e1c0111::BitReaderState468   int ReadBits(int nbits) {
469     FillBitWindow();
470     uint64_t val = (val_ >> (bits_left_ - nbits)) & ((1ULL << nbits) - 1);
471     bits_left_ -= nbits;
472     return val;
473   }
474 
475   // Sets *pos to the next stream position where parsing should continue.
476   // Enqueue the padding bits seen (0 or 1).
477   // Returns false if there is inconsistent or invalid padding or the stream
478   // ended too early.
FinishStreamjxl::jpeg::__anon59df6e1c0111::BitReaderState479   bool FinishStream(JPEGData* jpg, size_t* pos) {
480     int npadbits = bits_left_ & 7;
481     if (npadbits > 0) {
482       uint64_t padmask = (1ULL << npadbits) - 1;
483       uint64_t padbits = (val_ >> (bits_left_ - npadbits)) & padmask;
484       if (padbits != padmask) {
485         jpg->has_zero_padding_bit = true;
486       }
487       for (int i = npadbits - 1; i >= 0; --i) {
488         jpg->padding_bits.push_back((padbits >> i) & 1);
489       }
490     }
491     // Give back some bytes that we did not use.
492     int unused_bytes_left = bits_left_ >> 3;
493     while (unused_bytes_left-- > 0) {
494       --pos_;
495       // If we give back a 0 byte, we need to check if it was a 0xff/0x00 escape
496       // sequence, and if yes, we need to give back one more byte.
497       if (pos_ < next_marker_pos_ && data_[pos_] == 0 &&
498           data_[pos_ - 1] == 0xff) {
499         --pos_;
500       }
501     }
502     if (pos_ > next_marker_pos_) {
503       // Data ran out before the scan was complete.
504       JXL_JPEG_DEBUG("Unexpected end of scan.");
505       return false;
506     }
507     *pos = pos_;
508     return true;
509   }
510 
511   const uint8_t* data_;
512   const size_t len_;
513   size_t pos_;
514   uint64_t val_;
515   int bits_left_;
516   size_t next_marker_pos_;
517 };
518 
519 // Returns the next Huffman-coded symbol.
ReadSymbol(const HuffmanTableEntry * table,BitReaderState * br)520 int ReadSymbol(const HuffmanTableEntry* table, BitReaderState* br) {
521   int nbits;
522   br->FillBitWindow();
523   int val = (br->val_ >> (br->bits_left_ - 8)) & 0xff;
524   table += val;
525   nbits = table->bits - 8;
526   if (nbits > 0) {
527     br->bits_left_ -= 8;
528     table += table->value;
529     val = (br->val_ >> (br->bits_left_ - nbits)) & ((1 << nbits) - 1);
530     table += val;
531   }
532   br->bits_left_ -= table->bits;
533   return table->value;
534 }
535 
536 /**
537  * Returns the DC diff or AC value for extra bits value x and prefix code s.
538  *
539  * CCITT Rec. T.81 (1992 E)
540  * Table F.1 – Difference magnitude categories for DC coding
541  *  SSSS | DIFF values
542  * ------+--------------------------
543  *     0 | 0
544  *     1 | –1, 1
545  *     2 | –3, –2, 2, 3
546  *     3 | –7..–4, 4..7
547  * ......|..........................
548  *    11 | –2047..–1024, 1024..2047
549  *
550  * CCITT Rec. T.81 (1992 E)
551  * Table F.2 – Categories assigned to coefficient values
552  * [ Same as Table F.1, but does not include SSSS equal to 0 and 11]
553  *
554  *
555  * CCITT Rec. T.81 (1992 E)
556  * F.1.2.1.1 Structure of DC code table
557  * For each category,... additional bits... appended... to uniquely identify
558  * which difference... occurred... When DIFF is positive... SSSS... bits of DIFF
559  * are appended. When DIFF is negative... SSSS... bits of (DIFF – 1) are
560  * appended... Most significant bit... is 0 for negative differences and 1 for
561  * positive differences.
562  *
563  * In other words the upper half of extra bits range represents DIFF as is.
564  * The lower half represents the negative DIFFs with an offset.
565  */
HuffExtend(int x,int s)566 int HuffExtend(int x, int s) {
567   JXL_DASSERT(s >= 1);
568   int half = 1 << (s - 1);
569   if (x >= half) {
570     JXL_DASSERT(x < (1 << s));
571     return x;
572   } else {
573     return x - (1 << s) + 1;
574   }
575 }
576 
577 // Decodes one 8x8 block of DCT coefficients from the bit stream.
DecodeDCTBlock(const HuffmanTableEntry * dc_huff,const HuffmanTableEntry * ac_huff,int Ss,int Se,int Al,int * eobrun,bool * reset_state,int * num_zero_runs,BitReaderState * br,JPEGData * jpg,coeff_t * last_dc_coeff,coeff_t * coeffs)578 bool DecodeDCTBlock(const HuffmanTableEntry* dc_huff,
579                     const HuffmanTableEntry* ac_huff, int Ss, int Se, int Al,
580                     int* eobrun, bool* reset_state, int* num_zero_runs,
581                     BitReaderState* br, JPEGData* jpg, coeff_t* last_dc_coeff,
582                     coeff_t* coeffs) {
583   // Nowadays multiplication is even faster than variable shift.
584   int Am = 1 << Al;
585   bool eobrun_allowed = Ss > 0;
586   if (Ss == 0) {
587     int s = ReadSymbol(dc_huff, br);
588     if (s >= kJpegDCAlphabetSize) {
589       JXL_JPEG_DEBUG("Invalid Huffman symbol %d  for DC coefficient.", s);
590       jpg->error = JPEGReadError::INVALID_SYMBOL;
591       return false;
592     }
593     int diff = 0;
594     if (s > 0) {
595       int bits = br->ReadBits(s);
596       diff = HuffExtend(bits, s);
597     }
598     int coeff = diff + *last_dc_coeff;
599     const int dc_coeff = coeff * Am;
600     coeffs[0] = dc_coeff;
601     // TODO(eustas): is there a more elegant / explicit way to check this?
602     if (dc_coeff != coeffs[0]) {
603       JXL_JPEG_DEBUG("Invalid DC coefficient %d", dc_coeff);
604       jpg->error = JPEGReadError::NON_REPRESENTABLE_DC_COEFF;
605       return false;
606     }
607     *last_dc_coeff = coeff;
608     ++Ss;
609   }
610   if (Ss > Se) {
611     return true;
612   }
613   if (*eobrun > 0) {
614     --(*eobrun);
615     return true;
616   }
617   *num_zero_runs = 0;
618   for (int k = Ss; k <= Se; k++) {
619     int sr = ReadSymbol(ac_huff, br);
620     if (sr >= kJpegHuffmanAlphabetSize) {
621       JXL_JPEG_DEBUG("Invalid Huffman symbol %d for AC coefficient %d", sr, k);
622       jpg->error = JPEGReadError::INVALID_SYMBOL;
623       return false;
624     }
625     int r = sr >> 4;
626     int s = sr & 15;
627     if (s > 0) {
628       k += r;
629       if (k > Se) {
630         JXL_JPEG_DEBUG("Out-of-band coefficient %d band was %d-%d", k, Ss, Se);
631         jpg->error = JPEGReadError::OUT_OF_BAND_COEFF;
632         return false;
633       }
634       if (s + Al >= kJpegDCAlphabetSize) {
635         JXL_JPEG_DEBUG(
636             "Out of range AC coefficient value: s = %d Al = %d k = %d", s, Al,
637             k);
638         jpg->error = JPEGReadError::NON_REPRESENTABLE_AC_COEFF;
639         return false;
640       }
641       int bits = br->ReadBits(s);
642       int coeff = HuffExtend(bits, s);
643       coeffs[kJPEGNaturalOrder[k]] = coeff * Am;
644       *num_zero_runs = 0;
645     } else if (r == 15) {
646       k += 15;
647       ++(*num_zero_runs);
648     } else {
649       if (eobrun_allowed && k == Ss && *eobrun == 0) {
650         // We have two end-of-block runs right after each other, so we signal
651         // the jpeg encoder to force a state reset at this point.
652         *reset_state = true;
653       }
654       *eobrun = 1 << r;
655       if (r > 0) {
656         if (!eobrun_allowed) {
657           JXL_JPEG_DEBUG("End-of-block run crossing DC coeff.");
658           jpg->error = JPEGReadError::EOB_RUN_TOO_LONG;
659           return false;
660         }
661         *eobrun += br->ReadBits(r);
662       }
663       break;
664     }
665   }
666   --(*eobrun);
667   return true;
668 }
669 
RefineDCTBlock(const HuffmanTableEntry * ac_huff,int Ss,int Se,int Al,int * eobrun,bool * reset_state,BitReaderState * br,JPEGData * jpg,coeff_t * coeffs)670 bool RefineDCTBlock(const HuffmanTableEntry* ac_huff, int Ss, int Se, int Al,
671                     int* eobrun, bool* reset_state, BitReaderState* br,
672                     JPEGData* jpg, coeff_t* coeffs) {
673   // Nowadays multiplication is even faster than variable shift.
674   int Am = 1 << Al;
675   bool eobrun_allowed = Ss > 0;
676   if (Ss == 0) {
677     int s = br->ReadBits(1);
678     coeff_t dc_coeff = coeffs[0];
679     dc_coeff |= s * Am;
680     coeffs[0] = dc_coeff;
681     ++Ss;
682   }
683   if (Ss > Se) {
684     return true;
685   }
686   int p1 = Am;
687   int m1 = -Am;
688   int k = Ss;
689   int r;
690   int s;
691   bool in_zero_run = false;
692   if (*eobrun <= 0) {
693     for (; k <= Se; k++) {
694       s = ReadSymbol(ac_huff, br);
695       if (s >= kJpegHuffmanAlphabetSize) {
696         JXL_JPEG_DEBUG("Invalid Huffman symbol %d for AC coefficient %d", s, k);
697         jpg->error = JPEGReadError::INVALID_SYMBOL;
698         return false;
699       }
700       r = s >> 4;
701       s &= 15;
702       if (s) {
703         if (s != 1) {
704           JXL_JPEG_DEBUG("Invalid Huffman symbol %d for AC coefficient %d", s,
705                          k);
706           jpg->error = JPEGReadError::INVALID_SYMBOL;
707           return false;
708         }
709         s = br->ReadBits(1) ? p1 : m1;
710         in_zero_run = false;
711       } else {
712         if (r != 15) {
713           if (eobrun_allowed && k == Ss && *eobrun == 0) {
714             // We have two end-of-block runs right after each other, so we
715             // signal the jpeg encoder to force a state reset at this point.
716             *reset_state = true;
717           }
718           *eobrun = 1 << r;
719           if (r > 0) {
720             if (!eobrun_allowed) {
721               JXL_JPEG_DEBUG("End-of-block run crossing DC coeff.");
722               jpg->error = JPEGReadError::EOB_RUN_TOO_LONG;
723               return false;
724             }
725             *eobrun += br->ReadBits(r);
726           }
727           break;
728         }
729         in_zero_run = true;
730       }
731       do {
732         coeff_t thiscoef = coeffs[kJPEGNaturalOrder[k]];
733         if (thiscoef != 0) {
734           if (br->ReadBits(1)) {
735             if ((thiscoef & p1) == 0) {
736               if (thiscoef >= 0) {
737                 thiscoef += p1;
738               } else {
739                 thiscoef += m1;
740               }
741             }
742           }
743           coeffs[kJPEGNaturalOrder[k]] = thiscoef;
744         } else {
745           if (--r < 0) {
746             break;
747           }
748         }
749         k++;
750       } while (k <= Se);
751       if (s) {
752         if (k > Se) {
753           JXL_JPEG_DEBUG("Out-of-band coefficient %d band was %d-%d", k, Ss,
754                          Se);
755           jpg->error = JPEGReadError::OUT_OF_BAND_COEFF;
756           return false;
757         }
758         coeffs[kJPEGNaturalOrder[k]] = s;
759       }
760     }
761   }
762   if (in_zero_run) {
763     JXL_JPEG_DEBUG("Extra zero run before end-of-block.");
764     jpg->error = JPEGReadError::EXTRA_ZERO_RUN;
765     return false;
766   }
767   if (*eobrun > 0) {
768     for (; k <= Se; k++) {
769       coeff_t thiscoef = coeffs[kJPEGNaturalOrder[k]];
770       if (thiscoef != 0) {
771         if (br->ReadBits(1)) {
772           if ((thiscoef & p1) == 0) {
773             if (thiscoef >= 0) {
774               thiscoef += p1;
775             } else {
776               thiscoef += m1;
777             }
778           }
779         }
780         coeffs[kJPEGNaturalOrder[k]] = thiscoef;
781       }
782     }
783   }
784   --(*eobrun);
785   return true;
786 }
787 
ProcessRestart(const uint8_t * data,const size_t len,int * next_restart_marker,BitReaderState * br,JPEGData * jpg)788 bool ProcessRestart(const uint8_t* data, const size_t len,
789                     int* next_restart_marker, BitReaderState* br,
790                     JPEGData* jpg) {
791   size_t pos = 0;
792   if (!br->FinishStream(jpg, &pos)) {
793     jpg->error = JPEGReadError::INVALID_SCAN;
794     return false;
795   }
796   int expected_marker = 0xd0 + *next_restart_marker;
797   JXL_JPEG_EXPECT_MARKER();
798   int marker = data[pos + 1];
799   if (marker != expected_marker) {
800     JXL_JPEG_DEBUG("Did not find expected restart marker %d actual %d",
801                    expected_marker, marker);
802     jpg->error = JPEGReadError::WRONG_RESTART_MARKER;
803     return false;
804   }
805   br->Reset(pos + 2);
806   *next_restart_marker += 1;
807   *next_restart_marker &= 0x7;
808   return true;
809 }
810 
ProcessScan(const uint8_t * data,const size_t len,const std::vector<HuffmanTableEntry> & dc_huff_lut,const std::vector<HuffmanTableEntry> & ac_huff_lut,uint16_t scan_progression[kMaxComponents][kDCTBlockSize],bool is_progressive,size_t * pos,JPEGData * jpg)811 bool ProcessScan(const uint8_t* data, const size_t len,
812                  const std::vector<HuffmanTableEntry>& dc_huff_lut,
813                  const std::vector<HuffmanTableEntry>& ac_huff_lut,
814                  uint16_t scan_progression[kMaxComponents][kDCTBlockSize],
815                  bool is_progressive, size_t* pos, JPEGData* jpg) {
816   if (!ProcessSOS(data, len, pos, jpg)) {
817     return false;
818   }
819   JPEGScanInfo* scan_info = &jpg->scan_info.back();
820   bool is_interleaved = (scan_info->num_components > 1);
821   int max_h_samp_factor = 1;
822   int max_v_samp_factor = 1;
823   for (size_t i = 0; i < jpg->components.size(); ++i) {
824     max_h_samp_factor =
825         std::max(max_h_samp_factor, jpg->components[i].h_samp_factor);
826     max_v_samp_factor =
827         std::max(max_v_samp_factor, jpg->components[i].v_samp_factor);
828   }
829 
830   int MCU_rows = DivCeil(jpg->height, max_v_samp_factor * 8);
831   int MCUs_per_row = DivCeil(jpg->width, max_h_samp_factor * 8);
832   if (!is_interleaved) {
833     const JPEGComponent& c = jpg->components[scan_info->components[0].comp_idx];
834     MCUs_per_row = DivCeil(jpg->width * c.h_samp_factor, 8 * max_h_samp_factor);
835     MCU_rows = DivCeil(jpg->height * c.v_samp_factor, 8 * max_v_samp_factor);
836   }
837   coeff_t last_dc_coeff[kMaxComponents] = {0};
838   BitReaderState br(data, len, *pos);
839   int restarts_to_go = jpg->restart_interval;
840   int next_restart_marker = 0;
841   int eobrun = -1;
842   int block_scan_index = 0;
843   const int Al = is_progressive ? scan_info->Al : 0;
844   const int Ah = is_progressive ? scan_info->Ah : 0;
845   const int Ss = is_progressive ? scan_info->Ss : 0;
846   const int Se = is_progressive ? scan_info->Se : 63;
847   const uint16_t scan_bitmask = Ah == 0 ? (0xffff << Al) : (1u << Al);
848   const uint16_t refinement_bitmask = (1 << Al) - 1;
849   for (size_t i = 0; i < scan_info->num_components; ++i) {
850     int comp_idx = scan_info->components[i].comp_idx;
851     for (int k = Ss; k <= Se; ++k) {
852       if (scan_progression[comp_idx][k] & scan_bitmask) {
853         JXL_JPEG_DEBUG(
854             "Overlapping scans: component=%d k=%d prev_mask: %u cur_mask %u",
855             comp_idx, k, scan_progression[i][k], scan_bitmask);
856         jpg->error = JPEGReadError::OVERLAPPING_SCANS;
857         return false;
858       }
859       if (scan_progression[comp_idx][k] & refinement_bitmask) {
860         JXL_JPEG_DEBUG(
861             "Invalid scan order, a more refined scan was already done: "
862             "component=%d k=%d prev_mask=%u cur_mask=%u",
863             comp_idx, k, scan_progression[i][k], scan_bitmask);
864         jpg->error = JPEGReadError::INVALID_SCAN_ORDER;
865         return false;
866       }
867       scan_progression[comp_idx][k] |= scan_bitmask;
868     }
869   }
870   if (Al > 10) {
871     JXL_JPEG_DEBUG("Scan parameter Al=%d is not supported.", Al);
872     jpg->error = JPEGReadError::NON_REPRESENTABLE_AC_COEFF;
873     return false;
874   }
875   for (int mcu_y = 0; mcu_y < MCU_rows; ++mcu_y) {
876     for (int mcu_x = 0; mcu_x < MCUs_per_row; ++mcu_x) {
877       // Handle the restart intervals.
878       if (jpg->restart_interval > 0) {
879         if (restarts_to_go == 0) {
880           if (ProcessRestart(data, len, &next_restart_marker, &br, jpg)) {
881             restarts_to_go = jpg->restart_interval;
882             memset(static_cast<void*>(last_dc_coeff), 0, sizeof(last_dc_coeff));
883             if (eobrun > 0) {
884               JXL_JPEG_DEBUG("End-of-block run too long.");
885               jpg->error = JPEGReadError::EOB_RUN_TOO_LONG;
886               return false;
887             }
888             eobrun = -1;  // fresh start
889           } else {
890             return false;
891           }
892         }
893         --restarts_to_go;
894       }
895       // Decode one MCU.
896       for (size_t i = 0; i < scan_info->num_components; ++i) {
897         JPEGComponentScanInfo* si = &scan_info->components[i];
898         JPEGComponent* c = &jpg->components[si->comp_idx];
899         const HuffmanTableEntry* dc_lut =
900             &dc_huff_lut[si->dc_tbl_idx * kJpegHuffmanLutSize];
901         const HuffmanTableEntry* ac_lut =
902             &ac_huff_lut[si->ac_tbl_idx * kJpegHuffmanLutSize];
903         int nblocks_y = is_interleaved ? c->v_samp_factor : 1;
904         int nblocks_x = is_interleaved ? c->h_samp_factor : 1;
905         for (int iy = 0; iy < nblocks_y; ++iy) {
906           for (int ix = 0; ix < nblocks_x; ++ix) {
907             int block_y = mcu_y * nblocks_y + iy;
908             int block_x = mcu_x * nblocks_x + ix;
909             int block_idx = block_y * c->width_in_blocks + block_x;
910             bool reset_state = false;
911             int num_zero_runs = 0;
912             coeff_t* coeffs = &c->coeffs[block_idx * kDCTBlockSize];
913             if (Ah == 0) {
914               if (!DecodeDCTBlock(dc_lut, ac_lut, Ss, Se, Al, &eobrun,
915                                   &reset_state, &num_zero_runs, &br, jpg,
916                                   &last_dc_coeff[si->comp_idx], coeffs)) {
917                 return false;
918               }
919             } else {
920               if (!RefineDCTBlock(ac_lut, Ss, Se, Al, &eobrun, &reset_state,
921                                   &br, jpg, coeffs)) {
922                 return false;
923               }
924             }
925             if (reset_state) {
926               scan_info->reset_points.emplace_back(block_scan_index);
927             }
928             if (num_zero_runs > 0) {
929               JPEGScanInfo::ExtraZeroRunInfo info;
930               info.block_idx = block_scan_index;
931               info.num_extra_zero_runs = num_zero_runs;
932               scan_info->extra_zero_runs.push_back(info);
933             }
934             ++block_scan_index;
935           }
936         }
937       }
938     }
939   }
940   if (eobrun > 0) {
941     JXL_JPEG_DEBUG("End-of-block run too long.");
942     jpg->error = JPEGReadError::EOB_RUN_TOO_LONG;
943     return false;
944   }
945   if (!br.FinishStream(jpg, pos)) {
946     jpg->error = JPEGReadError::INVALID_SCAN;
947     return false;
948   }
949   if (*pos > len) {
950     JXL_JPEG_DEBUG("Unexpected end of file during scan. pos=%zu len=%zu", *pos,
951                    len);
952     jpg->error = JPEGReadError::UNEXPECTED_EOF;
953     return false;
954   }
955   return true;
956 }
957 
958 // Changes the quant_idx field of the components to refer to the index of the
959 // quant table in the jpg->quant array.
FixupIndexes(JPEGData * jpg)960 bool FixupIndexes(JPEGData* jpg) {
961   for (size_t i = 0; i < jpg->components.size(); ++i) {
962     JPEGComponent* c = &jpg->components[i];
963     bool found_index = false;
964     for (size_t j = 0; j < jpg->quant.size(); ++j) {
965       if (jpg->quant[j].index == c->quant_idx) {
966         c->quant_idx = j;
967         found_index = true;
968         break;
969       }
970     }
971     if (!found_index) {
972       JXL_JPEG_DEBUG("Quantization table with index %u not found",
973                      c->quant_idx);
974       jpg->error = JPEGReadError::QUANT_TABLE_NOT_FOUND;
975       return false;
976     }
977   }
978   return true;
979 }
980 
FindNextMarker(const uint8_t * data,const size_t len,size_t pos)981 size_t FindNextMarker(const uint8_t* data, const size_t len, size_t pos) {
982   // kIsValidMarker[i] == 1 means (0xc0 + i) is a valid marker.
983   static const uint8_t kIsValidMarker[] = {
984       1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
985       1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
986       1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
987   };
988   size_t num_skipped = 0;
989   while (pos + 1 < len && (data[pos] != 0xff || data[pos + 1] < 0xc0 ||
990                            !kIsValidMarker[data[pos + 1] - 0xc0])) {
991     ++pos;
992     ++num_skipped;
993   }
994   return num_skipped;
995 }
996 
997 }  // namespace
998 
ReadJpeg(const uint8_t * data,const size_t len,JpegReadMode mode,JPEGData * jpg)999 bool ReadJpeg(const uint8_t* data, const size_t len, JpegReadMode mode,
1000               JPEGData* jpg) {
1001   size_t pos = 0;
1002   // Check SOI marker.
1003   JXL_JPEG_EXPECT_MARKER();
1004   int marker = data[pos + 1];
1005   pos += 2;
1006   if (marker != 0xd8) {
1007     JXL_JPEG_DEBUG("Did not find expected SOI marker, actual=%d", marker);
1008     jpg->error = JPEGReadError::SOI_NOT_FOUND;
1009     return false;
1010   }
1011   int lut_size = kMaxHuffmanTables * kJpegHuffmanLutSize;
1012   std::vector<HuffmanTableEntry> dc_huff_lut(lut_size);
1013   std::vector<HuffmanTableEntry> ac_huff_lut(lut_size);
1014   bool found_sof = false;
1015   bool found_dri = false;
1016   uint16_t scan_progression[kMaxComponents][kDCTBlockSize] = {{0}};
1017 
1018   jpg->padding_bits.resize(0);
1019   bool is_progressive = false;  // default
1020   do {
1021     // Read next marker.
1022     size_t num_skipped = FindNextMarker(data, len, pos);
1023     if (num_skipped > 0) {
1024       // Add a fake marker to indicate arbitrary in-between-markers data.
1025       jpg->marker_order.push_back(0xff);
1026       jpg->inter_marker_data.emplace_back(data + pos, data + pos + num_skipped);
1027       pos += num_skipped;
1028     }
1029     JXL_JPEG_EXPECT_MARKER();
1030     marker = data[pos + 1];
1031     pos += 2;
1032     bool ok = true;
1033     switch (marker) {
1034       case 0xc0:
1035       case 0xc1:
1036       case 0xc2:
1037         is_progressive = (marker == 0xc2);
1038         ok = ProcessSOF(data, len, mode, &pos, jpg);
1039         found_sof = true;
1040         break;
1041       case 0xc4:
1042         ok = ProcessDHT(data, len, mode, &dc_huff_lut, &ac_huff_lut, &pos, jpg);
1043         break;
1044       case 0xd0:
1045       case 0xd1:
1046       case 0xd2:
1047       case 0xd3:
1048       case 0xd4:
1049       case 0xd5:
1050       case 0xd6:
1051       case 0xd7:
1052         // RST markers do not have any data.
1053         break;
1054       case 0xd9:
1055         // Found end marker.
1056         break;
1057       case 0xda:
1058         if (mode == JpegReadMode::kReadAll) {
1059           ok = ProcessScan(data, len, dc_huff_lut, ac_huff_lut,
1060                            scan_progression, is_progressive, &pos, jpg);
1061         }
1062         break;
1063       case 0xdb:
1064         ok = ProcessDQT(data, len, &pos, jpg);
1065         break;
1066       case 0xdd:
1067         ok = ProcessDRI(data, len, &pos, &found_dri, jpg);
1068         break;
1069       case 0xe0:
1070       case 0xe1:
1071       case 0xe2:
1072       case 0xe3:
1073       case 0xe4:
1074       case 0xe5:
1075       case 0xe6:
1076       case 0xe7:
1077       case 0xe8:
1078       case 0xe9:
1079       case 0xea:
1080       case 0xeb:
1081       case 0xec:
1082       case 0xed:
1083       case 0xee:
1084       case 0xef:
1085         if (mode != JpegReadMode::kReadTables) {
1086           ok = ProcessAPP(data, len, &pos, jpg);
1087         }
1088         break;
1089       case 0xfe:
1090         if (mode != JpegReadMode::kReadTables) {
1091           ok = ProcessCOM(data, len, &pos, jpg);
1092         }
1093         break;
1094       default:
1095         JXL_JPEG_DEBUG("Unsupported marker: %d pos=%zu len=%zu", marker, pos,
1096                        len);
1097         jpg->error = JPEGReadError::UNSUPPORTED_MARKER;
1098         ok = false;
1099         break;
1100     }
1101     if (!ok) {
1102       return false;
1103     }
1104     jpg->marker_order.push_back(marker);
1105     if (mode == JpegReadMode::kReadHeader && found_sof) {
1106       break;
1107     }
1108   } while (marker != 0xd9);
1109 
1110   if (!found_sof) {
1111     JXL_JPEG_DEBUG("Missing SOF marker.");
1112     jpg->error = JPEGReadError::SOF_NOT_FOUND;
1113     return false;
1114   }
1115 
1116   // Supplemental checks.
1117   if (mode == JpegReadMode::kReadAll) {
1118     if (pos < len) {
1119       jpg->tail_data = std::vector<uint8_t>(data + pos, data + len);
1120     }
1121     if (!FixupIndexes(jpg)) {
1122       return false;
1123     }
1124     if (jpg->huffman_code.empty()) {
1125       // Section B.2.4.2: "If a table has never been defined for a particular
1126       // destination, then when this destination is specified in a scan header,
1127       // the results are unpredictable."
1128       JXL_JPEG_DEBUG("Need at least one Huffman code table.");
1129       jpg->error = JPEGReadError::HUFFMAN_TABLE_ERROR;
1130       return false;
1131     }
1132     if (jpg->huffman_code.size() >= kMaxDHTMarkers) {
1133       JXL_JPEG_DEBUG("Too many Huffman tables.");
1134       jpg->error = JPEGReadError::HUFFMAN_TABLE_ERROR;
1135       return false;
1136     }
1137   }
1138   return true;
1139 }
1140 
1141 }  // namespace jpeg
1142 }  // namespace jxl
1143