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

Side by Side Diff: core/src/fxcodec/codec/fx_codec_jpx_opj.cpp

Issue 1016203002: Fix subtle issues in opj_skip_from_memory and add unit tests. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Fix type botch. Created 5 years, 9 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 | « core/src/fxcodec/codec/codec_int.h ('k') | core/src/fxcodec/codec/fx_codec_jpx_unittest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 PDFium Authors. All rights reserved. 1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 6
7 #include <limits>
8
7 #include "../../../include/fxcodec/fx_codec.h" 9 #include "../../../include/fxcodec/fx_codec.h"
8 #include "codec_int.h" 10 #include "codec_int.h"
9 #include "../fx_libopenjpeg/libopenjpeg20/openjpeg.h" 11 #include "../fx_libopenjpeg/libopenjpeg20/openjpeg.h"
10 #include "../lcms2/include/fx_lcms2.h" 12 #include "../lcms2/include/fx_lcms2.h"
13
11 static void fx_error_callback(const char *msg, void *client_data) 14 static void fx_error_callback(const char *msg, void *client_data)
12 { 15 {
13 (void)client_data; 16 (void)client_data;
14 } 17 }
15 static void fx_warning_callback(const char *msg, void *client_data) 18 static void fx_warning_callback(const char *msg, void *client_data)
16 { 19 {
17 (void)client_data; 20 (void)client_data;
18 } 21 }
19 static void fx_info_callback(const char *msg, void *client_data) 22 static void fx_info_callback(const char *msg, void *client_data)
20 { 23 {
21 (void)client_data; 24 (void)client_data;
22 } 25 }
23 struct DecodeData { 26 OPJ_SIZE_T opj_read_from_memory(void* p_buffer, OPJ_SIZE_T nb_bytes, void* p_use r_data)
24 unsigned char* src_data;
25 OPJ_SIZE_T src_size;
26 OPJ_SIZE_T offset;
27 };
28 static OPJ_SIZE_T opj_read_from_memory (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void* p_user_data)
29 { 27 {
30 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); 28 DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
31 if (srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL | | srcData->offset >= srcData->src_size) { 29 if (!srcData || !srcData->src_data || srcData->src_size == 0) {
30 return -1;
31 }
32 // Reads at EOF return an error code.
33 if (srcData->offset >= srcData->src_size) {
32 return -1; 34 return -1;
33 } 35 }
34 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset; 36 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset;
35 OPJ_SIZE_T readlength = p_nb_bytes < bufferLength ? p_nb_bytes : bufferLengt h; 37 OPJ_SIZE_T readlength = nb_bytes < bufferLength ? nb_bytes : bufferLength;
36 memcpy(p_buffer, &srcData->src_data[srcData->offset], readlength); 38 memcpy(p_buffer, &srcData->src_data[srcData->offset], readlength);
37 srcData->offset += readlength; 39 srcData->offset += readlength;
38 return readlength; 40 return readlength;
39 } 41 }
40 static OPJ_SIZE_T opj_write_from_memory (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void* p_user_data) 42 OPJ_SIZE_T opj_write_from_memory(void* p_buffer, OPJ_SIZE_T nb_bytes, void* p_us er_data)
41 { 43 {
42 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); 44 DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
43 if (srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL | | srcData->offset >= srcData->src_size) { 45 if (!srcData || !srcData->src_data || srcData->src_size == 0) {
46 return -1;
47 }
48 // Writes at EOF return an error code.
49 if (srcData->offset >= srcData->src_size) {
44 return -1; 50 return -1;
45 } 51 }
46 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset; 52 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset;
47 OPJ_SIZE_T writeLength = p_nb_bytes < bufferLength ? p_nb_bytes : bufferLeng th; 53 OPJ_SIZE_T writeLength = nb_bytes < bufferLength ? nb_bytes : bufferLength;
48 memcpy(&srcData->src_data[srcData->offset], p_buffer, writeLength); 54 memcpy(&srcData->src_data[srcData->offset], p_buffer, writeLength);
49 srcData->offset += writeLength; 55 srcData->offset += writeLength;
50 return writeLength; 56 return writeLength;
51 } 57 }
52 static OPJ_OFF_T opj_skip_from_memory (OPJ_OFF_T p_nb_bytes, void* p_user_data) 58 OPJ_OFF_T opj_skip_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data)
53 { 59 {
54 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); 60 DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
55 if (srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL) { 61 if (!srcData || !srcData->src_data || srcData->src_size == 0) {
56 return -1; 62 return -1;
57 } 63 }
58 if (srcData->offset >= srcData->src_size) { 64 // Offsets are signed and may indicate a negative skip. Do not support this
65 // because of the strange return convention where either bytes skipped or
66 // -1 is returned. Following that convention, a successful relative seek of
67 // -1 bytes would be required to to give the same result as the error case.
68 if (nb_bytes < 0) {
69 return -1;
70 }
71 // FIXME: use std::make_unsigned<OPJ_OFF_T>::type once c++11 lib is OK'd.
72 uint64_t unsignedNbBytes = static_cast<uint64_t>(nb_bytes);
73 // Additionally, the offset may take us beyond the range of a size_t (e.g.
74 // 32-bit platforms). If so, just clamp at EOF.
75 if (unsignedNbBytes > std::numeric_limits<OPJ_SIZE_T>::max() - srcData->offs et) {
59 srcData->offset = srcData->src_size; 76 srcData->offset = srcData->src_size;
60 return p_nb_bytes; 77 } else {
78 OPJ_SIZE_T checkedNbBytes = static_cast<OPJ_SIZE_T>(unsignedNbBytes);
79 // Otherwise, mimic fseek() semantics to always succeed, even past EOF,
80 // clamping at EOF. We can get away with this since we don't actually
81 // provide negative relative skips from beyond EOF back to inside the
82 // data, which would be the only reason to need to know exactly how far
83 // beyond EOF we are.
84 srcData->offset = std::min(srcData->offset + checkedNbBytes, srcData->sr c_size);
jun_fang 2015/03/19 00:28:46 In this case, we should return the skipped bytes r
Tom Sepez 2015/03/19 00:35:16 Looking at the example code you pointed at before,
jun_fang 2015/03/19 00:48:35 I checked the code before. I suspect that there ma
61 } 85 }
62 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset; 86 return nb_bytes;
63 OPJ_SIZE_T skipLength = p_nb_bytes < bufferLength ? p_nb_bytes : bufferLengt h;
64 srcData->offset += skipLength;
65 return skipLength;
66 } 87 }
67 static OPJ_BOOL opj_seek_from_memory (OPJ_OFF_T p_nb_bytes, void* p_user_data) 88 OPJ_BOOL opj_seek_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data)
68 { 89 {
69 DecodeData* srcData = static_cast<DecodeData*>(p_user_data); 90 DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
70 if (srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL) { 91 if (!srcData || !srcData->src_data || srcData->src_size == 0) {
71 return OPJ_FALSE; 92 return OPJ_FALSE;
72 } 93 }
73 if (srcData->offset >= srcData->src_size) { 94 // Offsets are signed and may indicate a negative position, which would
74 return OPJ_TRUE; 95 // be before the start of the file. Do not support this.
75 } 96 if (nb_bytes < 0) {
76 if (p_nb_bytes >= srcData->src_size) {
77 return OPJ_FALSE; 97 return OPJ_FALSE;
78 } 98 }
79 srcData->offset = p_nb_bytes; 99 // FIXME: use std::make_unsigned<OPJ_OFF_T>::type once c++11 lib is OK'd.
100 uint64_t unsignedNbBytes = static_cast<uint64_t>(nb_bytes);
101 // Additionally, the offset may take us beyond the range of a size_t (e.g.
102 // 32-bit platforms). If so, just clamp at EOF.
103 if (unsignedNbBytes > std::numeric_limits<OPJ_SIZE_T>::max()) {
104 srcData->offset = srcData->src_size;
jun_fang 2015/03/19 00:28:46 Before the code change, it returns false when the
Tom Sepez 2015/03/19 00:35:16 Looking at the example code again, static OPJ_BOOL
jun_fang 2015/03/19 00:48:35 OK. let's follow the implemention in open jpeg.
105 } else {
106 OPJ_SIZE_T checkedNbBytes = static_cast<OPJ_SIZE_T>(nb_bytes);
107 // Otherwise, mimic fseek() semantics to always succeed, even past EOF,
108 // again clamping at EOF.
109 srcData->offset = std::min(checkedNbBytes, srcData->src_size);
110 }
80 return OPJ_TRUE; 111 return OPJ_TRUE;
81 } 112 }
82 opj_stream_t* fx_opj_stream_create_memory_stream (DecodeData* data, OPJ_SIZE _T p_size, OPJ_BOOL p_is_read_stream) 113 opj_stream_t* fx_opj_stream_create_memory_stream (DecodeData* data, OPJ_SIZE _T p_size, OPJ_BOOL p_is_read_stream)
83 { 114 {
84 opj_stream_t* l_stream = 00; 115 opj_stream_t* l_stream = 00;
85 if (!data || ! data->src_data || data->src_size <= 0 ) { 116 if (!data || ! data->src_data || data->src_size <= 0 ) {
86 return NULL; 117 return NULL;
87 } 118 }
88 l_stream = opj_stream_create(p_size, p_is_read_stream); 119 l_stream = opj_stream_create(p_size, p_is_read_stream);
89 if (! l_stream) { 120 if (! l_stream) {
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 } 615 }
585 FX_BOOL CJPX_Decoder::Init(const unsigned char* src_data, int src_size) 616 FX_BOOL CJPX_Decoder::Init(const unsigned char* src_data, int src_size)
586 { 617 {
587 static const unsigned char szJP2Header[] = { 0x00, 0x00, 0x00, 0x0c, 0x6a, 0 x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a }; 618 static const unsigned char szJP2Header[] = { 0x00, 0x00, 0x00, 0x0c, 0x6a, 0 x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a };
588 if (!src_data || src_size < sizeof(szJP2Header)) { 619 if (!src_data || src_size < sizeof(szJP2Header)) {
589 return FALSE; 620 return FALSE;
590 } 621 }
591 image = NULL; 622 image = NULL;
592 m_SrcData = src_data; 623 m_SrcData = src_data;
593 m_SrcSize = src_size; 624 m_SrcSize = src_size;
594 DecodeData srcData; 625 DecodeData srcData(const_cast<unsigned char*>(src_data), src_size);
595 srcData.offset = 0;
596 srcData.src_size = src_size;
597 srcData.src_data = const_cast<unsigned char*>(src_data);
598 l_stream = fx_opj_stream_create_memory_stream(&srcData, OPJ_J2K_STREAM_CHUNK _SIZE, 1); 626 l_stream = fx_opj_stream_create_memory_stream(&srcData, OPJ_J2K_STREAM_CHUNK _SIZE, 1);
599 if (l_stream == NULL) { 627 if (l_stream == NULL) {
600 return FALSE; 628 return FALSE;
601 } 629 }
602 opj_dparameters_t parameters; 630 opj_dparameters_t parameters;
603 opj_set_default_decoder_parameters(&parameters); 631 opj_set_default_decoder_parameters(&parameters);
604 parameters.decod_format = 0; 632 parameters.decod_format = 0;
605 parameters.cod_format = 3; 633 parameters.cod_format = 3;
606 if(FXSYS_memcmp32(m_SrcData, szJP2Header, sizeof(szJP2Header)) == 0) { 634 if(FXSYS_memcmp32(m_SrcData, szJP2Header, sizeof(szJP2Header)) == 0) {
607 l_codec = opj_create_decompress(OPJ_CODEC_JP2); 635 l_codec = opj_create_decompress(OPJ_CODEC_JP2);
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 FX_BOOL CCodec_JpxModule::Decode(void* ctx, FX_LPBYTE dest_data, int pitch, FX_B OOL bTranslateColor, FX_LPBYTE offsets) 820 FX_BOOL CCodec_JpxModule::Decode(void* ctx, FX_LPBYTE dest_data, int pitch, FX_B OOL bTranslateColor, FX_LPBYTE offsets)
793 { 821 {
794 CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx; 822 CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
795 return pDecoder->Decode(dest_data, pitch, bTranslateColor, offsets); 823 return pDecoder->Decode(dest_data, pitch, bTranslateColor, offsets);
796 } 824 }
797 void CCodec_JpxModule::DestroyDecoder(void* ctx) 825 void CCodec_JpxModule::DestroyDecoder(void* ctx)
798 { 826 {
799 CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx; 827 CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
800 delete pDecoder; 828 delete pDecoder;
801 } 829 }
OLDNEW
« no previous file with comments | « core/src/fxcodec/codec/codec_int.h ('k') | core/src/fxcodec/codec/fx_codec_jpx_unittest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698