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

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: Address review comments. 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 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 #endif 468 #endif
467 if (overrideColorSpace == JCS_YCbCr) { 469 if (overrideColorSpace == JCS_YCbCr) {
468 m_info.out_color_space = JCS_YCbCr; 470 m_info.out_color_space = JCS_YCbCr;
469 m_info.raw_data_out = TRUE; 471 m_info.raw_data_out = TRUE;
470 m_uvSize = computeYUVSize(&m_info, 1, ImageDecoder::SizeForMemor yAllocation); // U size and V size have to be the same if we got here 472 m_uvSize = computeYUVSize(&m_info, 1, ImageDecoder::SizeForMemor yAllocation); // U size and V size have to be the same if we got here
471 } 473 }
472 474
473 // Don't allocate a giant and superfluous memory buffer when the 475 // Don't allocate a giant and superfluous memory buffer when the
474 // image is a sequential JPEG. 476 // image is a sequential JPEG.
475 m_info.buffered_image = jpeg_has_multiple_scans(&m_info); 477 m_info.buffered_image = jpeg_has_multiple_scans(&m_info);
478 if (m_info.buffered_image) {
479 m_err.pub.emit_message = emit_message;
480 m_err.num_corrupt_warnings = 0;
481 }
476 482
477 if (onlySize) { 483 if (onlySize) {
478 // We can stop here. Reduce our buffer length and available data . 484 // We can stop here. Reduce our buffer length and available data .
479 m_bufferLength -= m_info.src->bytes_in_buffer; 485 m_bufferLength -= m_info.src->bytes_in_buffer;
480 m_info.src->bytes_in_buffer = 0; 486 m_info.src->bytes_in_buffer = 0;
481 return true; 487 return true;
482 } 488 }
483 // FALL THROUGH 489 // FALL THROUGH
484 490
485 case JPEG_START_DECOMPRESS: 491 case JPEG_START_DECOMPRESS:
486 // Set parameters for decompression. 492 // Set parameters for decompression.
487 // FIXME -- Should reset dct_method and dither mode for final pass 493 // FIXME -- Should reset dct_method and dither mode for final pass
488 // of progressive JPEG. 494 // of progressive JPEG.
489 m_info.dct_method = dctMethod(); 495 m_info.dct_method = dctMethod();
490 m_info.dither_mode = ditherMode(); 496 m_info.dither_mode = ditherMode();
491 m_info.do_fancy_upsampling = doFancyUpsampling(); 497 m_info.do_fancy_upsampling = doFancyUpsampling();
498 m_info.do_block_smoothing = true;
492 m_info.enable_2pass_quant = false; 499 m_info.enable_2pass_quant = false;
493 m_info.do_block_smoothing = true; 500 // FIXME: should we just assert these?
501 m_info.enable_external_quant = false;
502 m_info.enable_1pass_quant = false;
503 m_info.quantize_colors = false;
504 m_info.colormap = 0;
494 505
495 // Make a one-row-high sample array that will go away when done with 506 // 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 507 // 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 508 // uses the IJG memory manager, it must be allocated before the call
498 // to jpeg_start_compress(). 509 // to jpeg_start_compress().
499 // FIXME: note that some output color spaces do not need the samples 510 // FIXME: note that some output color spaces do not need the samples
500 // buffer. Remove this allocation for those color spaces. 511 // buffer. Remove this allocation for those color spaces.
501 { 512 {
502 int samplesWidth = (m_info.out_color_space == JCS_YCbCr) ? compu teYUVSize(&m_info, 0, ImageDecoder::SizeForMemoryAllocation).width() : m_info.ou tput_width; 513 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); 514 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... 531 // If we've completed image output...
521 ASSERT(m_info.output_scanline == m_info.output_height); 532 ASSERT(m_info.output_scanline == m_info.output_height);
522 m_state = JPEG_DONE; 533 m_state = JPEG_DONE;
523 } 534 }
524 // FALL THROUGH 535 // FALL THROUGH
525 536
526 case JPEG_DECOMPRESS_PROGRESSIVE: 537 case JPEG_DECOMPRESS_PROGRESSIVE:
527 if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) { 538 if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) {
528 int status; 539 int status;
529 do { 540 do {
541 decoder_error_mgr* err = reinterpret_cast_ptr<decoder_error_ mgr *>(m_info.err);
542 if (err->num_corrupt_warnings)
543 break;
530 status = jpeg_consume_input(&m_info); 544 status = jpeg_consume_input(&m_info);
531 } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_E OI)); 545 } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_E OI));
532 546
533 for (;;) { 547 for (;;) {
534 if (!m_info.output_scanline) { 548 if (!m_info.output_scanline) {
535 int scan = m_info.input_scan_number; 549 int scan = m_info.input_scan_number;
536 550
537 // If we haven't displayed anything yet 551 // If we haven't displayed anything yet
538 // (output_scan_number == 0) and we have enough data for 552 // (output_scan_number == 0) and we have enough data for
539 // a complete scan, force output of the last full scan. 553 // a complete scan, force output of the last full scan.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 649
636 #if USE(QCMSLIB) 650 #if USE(QCMSLIB)
637 qcms_transform* m_transform; 651 qcms_transform* m_transform;
638 #endif 652 #endif
639 }; 653 };
640 654
641 // Override the standard error method in the IJG JPEG decoder code. 655 // Override the standard error method in the IJG JPEG decoder code.
642 void error_exit(j_common_ptr cinfo) 656 void error_exit(j_common_ptr cinfo)
643 { 657 {
644 // Return control to the setjmp point. 658 // Return control to the setjmp point.
645 decoder_error_mgr *err = reinterpret_cast_ptr<decoder_error_mgr *>(cinfo->er r); 659 decoder_error_mgr* err = reinterpret_cast_ptr<decoder_error_mgr *>(cinfo->er r);
646 longjmp(err->setjmp_buffer, -1); 660 longjmp(err->setjmp_buffer, -1);
647 } 661 }
648 662
663 void emit_message(j_common_ptr cinfo, int msg_level)
664 {
665 if (msg_level >= 0)
666 return;
667
668 decoder_error_mgr* err = reinterpret_cast_ptr<decoder_error_mgr *>(cinfo->er r);
669 err->pub.num_warnings++;
670
671 // Detect and count corrupt JPEG warning messages.
672 const char* warning = 0;
673 int code = err->pub.msg_code;
674 if (code > 0 && code <= err->pub.last_jpeg_message)
675 warning = err->pub.jpeg_message_table[code];
676 if (warning && !strncmp("Corrupt JPEG", warning, 12))
677 err->num_corrupt_warnings++;
678 }
679
649 void init_source(j_decompress_ptr) 680 void init_source(j_decompress_ptr)
650 { 681 {
651 } 682 }
652 683
653 void skip_input_data(j_decompress_ptr jd, long num_bytes) 684 void skip_input_data(j_decompress_ptr jd, long num_bytes)
654 { 685 {
655 decoder_source_mgr *src = (decoder_source_mgr *)jd->src; 686 decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
656 src->decoder->skipBytes(num_bytes); 687 src->decoder->skipBytes(num_bytes);
657 } 688 }
658 689
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 // has failed. 992 // has failed.
962 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) 993 if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived())
963 setFailed(); 994 setFailed();
964 995
965 // If decoding is done or failed, we don't need the JPEGImageReader anymore. 996 // If decoding is done or failed, we don't need the JPEGImageReader anymore.
966 if (isComplete(this, onlySize) || failed()) 997 if (isComplete(this, onlySize) || failed())
967 m_reader.clear(); 998 m_reader.clear();
968 } 999 }
969 1000
970 } 1001 }
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