Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: Source/platform/image-decoders/jpeg/JPEGImageDecoder.cpp

Issue 1180013006: Do not consume input of corrupt progressive JPEG (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006 Apple Computer, Inc. 2 * Copyright (C) 2006 Apple Computer, Inc.
3 * 3 *
4 * Portions are Copyright (C) 2001-6 mozilla.org 4 * Portions are Copyright (C) 2001-6 mozilla.org
5 * 5 *
6 * Other contributors: 6 * Other contributors:
7 * Stuart Parmenter <stuart@mozilla.com> 7 * Stuart Parmenter <stuart@mozilla.com>
8 * 8 *
9 * This library is free software; you can redistribute it and/or 9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public 10 * modify it under the terms of the GNU Lesser General Public
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 82
83 // JPEG only supports a denominator of 8. 83 // JPEG only supports a denominator of 8.
84 const unsigned scaleDenominator = 8; 84 const unsigned scaleDenominator = 8;
85 85
86 } // namespace 86 } // namespace
87 87
88 namespace blink { 88 namespace blink {
89 89
90 struct decoder_error_mgr { 90 struct decoder_error_mgr {
91 struct jpeg_error_mgr pub; // "public" fields for IJG library 91 struct jpeg_error_mgr pub; // "public" fields for IJG library
92 int num_corrupt_warnings; // Counts corrupt warning messages
92 jmp_buf setjmp_buffer; // For handling catastropic errors 93 jmp_buf setjmp_buffer; // For handling catastropic errors
93 }; 94 };
94 95
95 enum jstate { 96 enum jstate {
96 JPEG_HEADER, // Reading JFIF headers 97 JPEG_HEADER, // Reading JFIF headers
97 JPEG_START_DECOMPRESS, 98 JPEG_START_DECOMPRESS,
98 JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels 99 JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels
99 JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels 100 JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels
100 JPEG_DONE, 101 JPEG_DONE,
101 JPEG_ERROR 102 JPEG_ERROR
102 }; 103 };
103 104
104 enum yuv_subsampling { 105 enum yuv_subsampling {
105 YUV_UNKNOWN, 106 YUV_UNKNOWN,
106 YUV_410, 107 YUV_410,
107 YUV_411, 108 YUV_411,
108 YUV_420, 109 YUV_420,
109 YUV_422, 110 YUV_422,
110 YUV_440, 111 YUV_440,
111 YUV_444 112 YUV_444
112 }; 113 };
113 114
114 void init_source(j_decompress_ptr jd); 115 void init_source(j_decompress_ptr jd);
115 boolean fill_input_buffer(j_decompress_ptr jd); 116 boolean fill_input_buffer(j_decompress_ptr jd);
116 void skip_input_data(j_decompress_ptr jd, long num_bytes); 117 void skip_input_data(j_decompress_ptr jd, long num_bytes);
117 void term_source(j_decompress_ptr jd); 118 void term_source(j_decompress_ptr jd);
118 void error_exit(j_common_ptr cinfo); 119 void error_exit(j_common_ptr cinfo);
120 void emit_message(j_common_ptr cinfo, int msg_level);
119 121
120 // Implementation of a JPEG src object that understands our state machine 122 // Implementation of a JPEG src object that understands our state machine
121 struct decoder_source_mgr { 123 struct decoder_source_mgr {
122 // public fields; must be first in this struct! 124 // public fields; must be first in this struct!
123 struct jpeg_source_mgr pub; 125 struct jpeg_source_mgr pub;
124 126
125 JPEGImageReader* decoder; 127 JPEGImageReader* decoder;
126 }; 128 };
127 129
128 static unsigned readUint16(JOCTET* data, bool isBigEndian) 130 static unsigned readUint16(JOCTET* data, bool isBigEndian)
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 , m_bufferLength(0) 307 , m_bufferLength(0)
306 , m_bytesToSkip(0) 308 , m_bytesToSkip(0)
307 , m_state(JPEG_HEADER) 309 , m_state(JPEG_HEADER)
308 , m_samples(0) 310 , m_samples(0)
309 #if USE(QCMSLIB) 311 #if USE(QCMSLIB)
310 , m_transform(0) 312 , m_transform(0)
311 #endif 313 #endif
312 { 314 {
313 memset(&m_info, 0, sizeof(jpeg_decompress_struct)); 315 memset(&m_info, 0, sizeof(jpeg_decompress_struct));
314 316
315 // Set up the normal JPEG error routines, then override error_exit. 317 // Set up the normal JPEG error routines and install overrides.
316 m_info.err = jpeg_std_error(&m_err.pub); 318 m_info.err = jpeg_std_error(&m_err.pub);
319 m_err.pub.emit_message = emit_message;
scroggo_chromium 2015/06/15 15:57:06 Besides error reporting, it looks like the behavio
Noel Gordon 2015/06/18 12:10:07 Good points. Since we have corruption for sequent
317 m_err.pub.error_exit = error_exit; 320 m_err.pub.error_exit = error_exit;
321 m_err.num_corrupt_warnings = 0;
318 322
319 // Allocate and initialize JPEG decompression object. 323 // Allocate and initialize JPEG decompression object.
320 jpeg_create_decompress(&m_info); 324 jpeg_create_decompress(&m_info);
321 325
322 ASSERT(!m_info.src); 326 ASSERT(!m_info.src);
323 decoder_source_mgr* src = (decoder_source_mgr*)fastZeroedMalloc(sizeof(d ecoder_source_mgr)); 327 decoder_source_mgr* src = (decoder_source_mgr*)fastZeroedMalloc(sizeof(d ecoder_source_mgr));
324 if (!src) { 328 if (!src) {
325 m_state = JPEG_ERROR; 329 m_state = JPEG_ERROR;
326 return; 330 return;
327 } 331 }
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 } 486 }
483 // FALL THROUGH 487 // FALL THROUGH
484 488
485 case JPEG_START_DECOMPRESS: 489 case JPEG_START_DECOMPRESS:
486 // Set parameters for decompression. 490 // Set parameters for decompression.
487 // FIXME -- Should reset dct_method and dither mode for final pass 491 // FIXME -- Should reset dct_method and dither mode for final pass
488 // of progressive JPEG. 492 // of progressive JPEG.
489 m_info.dct_method = dctMethod(); 493 m_info.dct_method = dctMethod();
490 m_info.dither_mode = ditherMode(); 494 m_info.dither_mode = ditherMode();
491 m_info.do_fancy_upsampling = doFancyUpsampling(); 495 m_info.do_fancy_upsampling = doFancyUpsampling();
496 m_info.do_block_smoothing = true;
492 m_info.enable_2pass_quant = false; 497 m_info.enable_2pass_quant = false;
493 m_info.do_block_smoothing = true; 498 m_info.enable_external_quant = false;
scroggo_chromium 2015/06/15 15:57:06 Are these (setting to false and 0) necessary or ju
Noel Gordon 2015/06/18 12:10:07 For completeness. Two variables related to buffere
scroggo_chromium 2015/06/18 13:19:24 Either way. I just wanted to make sure I understan
499 m_info.enable_1pass_quant = false;
500 m_info.quantize_colors = false;
501 m_info.colormap = 0;
494 502
495 // Make a one-row-high sample array that will go away when done with 503 // Make a one-row-high sample array that will go away when done with
496 // image. Always make it big enough to hold an RGB row. Since this 504 // image. Always make it big enough to hold an RGB row. Since this
497 // uses the IJG memory manager, it must be allocated before the call 505 // uses the IJG memory manager, it must be allocated before the call
498 // to jpeg_start_compress(). 506 // to jpeg_start_compress().
499 // FIXME: note that some output color spaces do not need the samples 507 // FIXME: note that some output color spaces do not need the samples
500 // buffer. Remove this allocation for those color spaces. 508 // buffer. Remove this allocation for those color spaces.
501 { 509 {
502 int samplesWidth = (m_info.out_color_space == JCS_YCbCr) ? compu teYUVSize(&m_info, 0, ImageDecoder::SizeForMemoryAllocation).width() : m_info.ou tput_width; 510 int samplesWidth = (m_info.out_color_space == JCS_YCbCr) ? compu teYUVSize(&m_info, 0, ImageDecoder::SizeForMemoryAllocation).width() : m_info.ou tput_width;
503 m_samples = (*m_info.mem->alloc_sarray)(reinterpret_cast<j_commo n_ptr>(&m_info), JPOOL_IMAGE, samplesWidth * 4, 1); 511 m_samples = (*m_info.mem->alloc_sarray)(reinterpret_cast<j_commo n_ptr>(&m_info), JPOOL_IMAGE, samplesWidth * 4, 1);
(...skipping 16 matching lines...) Expand all
520 // If we've completed image output... 528 // If we've completed image output...
521 ASSERT(m_info.output_scanline == m_info.output_height); 529 ASSERT(m_info.output_scanline == m_info.output_height);
522 m_state = JPEG_DONE; 530 m_state = JPEG_DONE;
523 } 531 }
524 // FALL THROUGH 532 // FALL THROUGH
525 533
526 case JPEG_DECOMPRESS_PROGRESSIVE: 534 case JPEG_DECOMPRESS_PROGRESSIVE:
527 if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) { 535 if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) {
528 int status; 536 int status;
529 do { 537 do {
538 decoder_error_mgr* err = reinterpret_cast_ptr<decoder_error_ mgr *>(m_info.err);
539 if (err->num_corrupt_warnings)
540 break;
530 status = jpeg_consume_input(&m_info); 541 status = jpeg_consume_input(&m_info);
531 } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_E OI)); 542 } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_E OI));
532 543
533 for (;;) { 544 for (;;) {
534 if (!m_info.output_scanline) { 545 if (!m_info.output_scanline) {
535 int scan = m_info.input_scan_number; 546 int scan = m_info.input_scan_number;
536 547
537 // If we haven't displayed anything yet 548 // If we haven't displayed anything yet
538 // (output_scan_number == 0) and we have enough data for 549 // (output_scan_number == 0) and we have enough data for
539 // a complete scan, force output of the last full scan. 550 // a complete scan, force output of the last full scan.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 646
636 #if USE(QCMSLIB) 647 #if USE(QCMSLIB)
637 qcms_transform* m_transform; 648 qcms_transform* m_transform;
638 #endif 649 #endif
639 }; 650 };
640 651
641 // Override the standard error method in the IJG JPEG decoder code. 652 // Override the standard error method in the IJG JPEG decoder code.
642 void error_exit(j_common_ptr cinfo) 653 void error_exit(j_common_ptr cinfo)
643 { 654 {
644 // Return control to the setjmp point. 655 // Return control to the setjmp point.
645 decoder_error_mgr *err = reinterpret_cast_ptr<decoder_error_mgr *>(cinfo->er r); 656 decoder_error_mgr* err = reinterpret_cast_ptr<decoder_error_mgr *>(cinfo->er r);
646 longjmp(err->setjmp_buffer, -1); 657 longjmp(err->setjmp_buffer, -1);
647 } 658 }
648 659
660 void emit_message(j_common_ptr cinfo, int msg_level)
661 {
662 if (msg_level >= 0)
663 return;
664
665 decoder_error_mgr* err = reinterpret_cast_ptr<decoder_error_mgr *>(cinfo->er r);
666 err->pub.num_warnings++;
667
668 // Detect and count corrupt JPEG warning messages.
669 const char* warning = 0;
670 int code = err->pub.msg_code;
671 if (code > 0 && code <= err->pub.last_jpeg_message)
672 warning = err->pub.jpeg_message_table[code];
673 if (warning && !strncmp("Corrupt JPEG", warning, 12))
674 err->num_corrupt_warnings++;
scroggo_chromium 2015/06/15 15:57:05 This appears to be used as a boolean. Do we need t
Noel Gordon 2015/06/18 12:10:07 For debug but also compat with the way libjpeg int
scroggo_chromium 2015/06/18 13:19:24 sgtm
675 }
676
649 void init_source(j_decompress_ptr) 677 void init_source(j_decompress_ptr)
650 { 678 {
651 } 679 }
652 680
653 void skip_input_data(j_decompress_ptr jd, long num_bytes) 681 void skip_input_data(j_decompress_ptr jd, long num_bytes)
654 { 682 {
655 decoder_source_mgr *src = (decoder_source_mgr *)jd->src; 683 decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
656 src->decoder->skipBytes(num_bytes); 684 src->decoder->skipBytes(num_bytes);
657 } 685 }
658 686
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 // has failed. 989 // has failed.
962 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) 990 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived())
963 setFailed(); 991 setFailed();
964 992
965 // If decoding is done or failed, we don't need the JPEGImageReader anymore. 993 // If decoding is done or failed, we don't need the JPEGImageReader anymore.
966 if (isComplete(this, onlySize) || failed()) 994 if (isComplete(this, onlySize) || failed())
967 m_reader.clear(); 995 m_reader.clear();
968 } 996 }
969 997
970 } 998 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698