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

Side by Side Diff: src/core/SkColorSpace_ICC.cpp

Issue 2257983003: Add checks for bogus profiles to SkColorSpace::NewICC() (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Relax constraints Created 4 years, 2 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 | tests/ColorSpaceTest.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 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkColorSpace.h" 8 #include "SkColorSpace.h"
9 #include "SkColorSpace_Base.h" 9 #include "SkColorSpace_Base.h"
10 #include "SkColorSpacePriv.h" 10 #include "SkColorSpacePriv.h"
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 void init(const uint8_t* src, size_t len) { 103 void init(const uint8_t* src, size_t len) {
104 SkASSERT(kICCHeaderSize == sizeof(*this)); 104 SkASSERT(kICCHeaderSize == sizeof(*this));
105 105
106 uint32_t* dst = (uint32_t*) this; 106 uint32_t* dst = (uint32_t*) this;
107 for (uint32_t i = 0; i < kICCHeaderSize / 4; i++, src+=4) { 107 for (uint32_t i = 0; i < kICCHeaderSize / 4; i++, src+=4) {
108 dst[i] = read_big_endian_u32(src); 108 dst[i] = read_big_endian_u32(src);
109 } 109 }
110 } 110 }
111 111
112 bool valid() const { 112 bool valid() const {
113 return_if_false(fSize >= kICCHeaderSize, "Size is too small"); 113 SkASSERT(fSize >= kICCHeaderSize);
114 114
115 uint8_t majorVersion = fVersion >> 24; 115 uint8_t majorVersion = fVersion >> 24;
116 return_if_false(majorVersion <= 4, "Unsupported version"); 116 return_if_false(majorVersion <= 4, "Unsupported version");
117 117
118 // These are the four basic classes of profiles that we might expect to see embedded 118 // These are the four basic classes of profiles that we might expect to see embedded
119 // in images. Additional classes exist, but they generally are used as a convenient 119 // in images. Additional classes exist, but they generally are used as a convenient
120 // way for CMMs to store calculated transforms. 120 // way for CMMs to store calculated transforms.
121 return_if_false(fProfileClass == kDisplay_Profile || 121 return_if_false(fProfileClass == kDisplay_Profile ||
122 fProfileClass == kInput_Profile || 122 fProfileClass == kInput_Profile ||
123 fProfileClass == kOutput_Profile || 123 fProfileClass == kOutput_Profile ||
(...skipping 18 matching lines...) Expand all
142 // Warn rather than fail here. Occasionally, we see perfectly 142 // Warn rather than fail here. Occasionally, we see perfectly
143 // normal profiles with wacky rendering intents. 143 // normal profiles with wacky rendering intents.
144 SkColorSpacePrintf("Warning, bad rendering intent.\n"); 144 SkColorSpacePrintf("Warning, bad rendering intent.\n");
145 } 145 }
146 146
147 return_if_false(color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[0 ]), 0.96420f) && 147 return_if_false(color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[0 ]), 0.96420f) &&
148 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1 ]), 1.00000f) && 148 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1 ]), 1.00000f) &&
149 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2 ]), 0.82491f), 149 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2 ]), 0.82491f),
150 "Illuminant must be D50"); 150 "Illuminant must be D50");
151 151
152 // Arbitrary, but there's no reason to exceed 100 tags.
152 return_if_false(fTagCount <= 100, "Too many tags"); 153 return_if_false(fTagCount <= 100, "Too many tags");
153 154
154 return true; 155 return true;
155 } 156 }
156 }; 157 };
157 158
158 template <class T> 159 template <class T>
159 static bool safe_add(T arg1, T arg2, size_t* result) { 160 static bool safe_add(T arg1, T arg2, size_t* result) {
160 SkASSERT(arg1 >= 0); 161 SkASSERT(arg1 >= 0);
161 SkASSERT(arg2 >= 0); 162 SkASSERT(arg2 >= 0);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 // In the case of consecutive gamma tags, we need to count the number of byt es in the 285 // In the case of consecutive gamma tags, we need to count the number of byt es in the
285 // tag, so that we can move on to the next tag. 286 // tag, so that we can move on to the next tag.
286 size_t tagBytes; 287 size_t tagBytes;
287 288
288 uint32_t type = read_big_endian_u32(src); 289 uint32_t type = read_big_endian_u32(src);
289 // Bytes 4-7 are reserved and should be set to zero. 290 // Bytes 4-7 are reserved and should be set to zero.
290 switch (type) { 291 switch (type) {
291 case kTAG_CurveType: { 292 case kTAG_CurveType: {
292 uint32_t count = read_big_endian_u32(src + 8); 293 uint32_t count = read_big_endian_u32(src + 8);
293 294
295 // This is arbitrary, but one million entries is more than enough fo r a table.
296 static constexpr size_t kMaxGammaTableSize = 2 << 20;
297 if (count > kMaxGammaTableSize) {
298 SkColorSpacePrintf("Gamma table too large");
299 return SkGammas::Type::kNone_Type;
300 }
301
294 // tagBytes = 12 + 2 * count 302 // tagBytes = 12 + 2 * count
295 // We need to do safe addition here to avoid integer overflow. 303 // We need to do safe addition here to avoid integer overflow.
296 if (!safe_add(count, count, &tagBytes) || 304 if (!safe_add(count, count, &tagBytes) ||
297 !safe_add((size_t) 12, tagBytes, &tagBytes)) 305 !safe_add((size_t) 12, tagBytes, &tagBytes))
298 { 306 {
299 SkColorSpacePrintf("Invalid gamma count"); 307 SkColorSpacePrintf("Invalid gamma count");
300 return SkGammas::Type::kNone_Type; 308 return SkGammas::Type::kNone_Type;
301 } 309 }
302 310
303 if (len < tagBytes) { 311 if (len < tagBytes) {
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 } 874 }
867 875
868 if (a->fOffset == b->fOffset) { 876 if (a->fOffset == b->fOffset) {
869 return true; 877 return true;
870 } 878 }
871 879
872 return !memcmp(a->addr(base), b->addr(base), a->fLength); 880 return !memcmp(a->addr(base), b->addr(base), a->fLength);
873 } 881 }
874 882
875 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { 883 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) {
876 if (!input || len < kICCHeaderSize) { 884 // This is arbitrary, but there's no need for a sane profile to exceed 4 MB.
885 static constexpr size_t kMaxICCSize = 2 << 22;
886
887 if (!input || kICCHeaderSize > len || len > kMaxICCSize) {
877 return_null("Data is null or not large enough to contain an ICC profile" ); 888 return_null("Data is null or not large enough to contain an ICC profile" );
878 } 889 }
879 890
880 // Create our own copy of the input. 891 // Create our own copy of the input.
881 void* memory = sk_malloc_throw(len); 892 void* memory = sk_malloc_throw(len);
882 memcpy(memory, input, len); 893 memcpy(memory, input, len);
883 sk_sp<SkData> data = SkData::MakeFromMalloc(memory, len); 894 sk_sp<SkData> data = SkData::MakeFromMalloc(memory, len);
884 const uint8_t* base = data->bytes(); 895 const uint8_t* base = data->bytes();
885 const uint8_t* ptr = base; 896 const uint8_t* ptr = base;
886 897
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
1302 ptr32[4] = SkEndian_SwapBE32(0x000116cc); 1313 ptr32[4] = SkEndian_SwapBE32(0x000116cc);
1303 ptr += kTAG_XYZ_Bytes; 1314 ptr += kTAG_XYZ_Bytes;
1304 1315
1305 // Write copyright tag 1316 // Write copyright tag
1306 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); 1317 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag));
1307 1318
1308 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if 1319 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if
1309 // the client calls again? 1320 // the client calls again?
1310 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); 1321 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize);
1311 } 1322 }
OLDNEW
« no previous file with comments | « no previous file | tests/ColorSpaceTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698