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

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

Issue 2053683002: SkColorSpace::NewICC fix integer overflow caught by fuzzer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 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 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 "SkEndian.h" 10 #include "SkEndian.h"
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1 ]), 1.00000f) && 307 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[1 ]), 1.00000f) &&
308 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2 ]), 0.82491f), 308 color_space_almost_equal(SkFixedToFloat(fIlluminantXYZ[2 ]), 0.82491f),
309 "Illuminant must be D50"); 309 "Illuminant must be D50");
310 310
311 return_if_false(fTagCount <= 100, "Too many tags"); 311 return_if_false(fTagCount <= 100, "Too many tags");
312 312
313 return true; 313 return true;
314 } 314 }
315 }; 315 };
316 316
317 template <class T>
318 static bool safe_add(T arg1, T arg2, size_t* result) {
319 SkASSERT(arg1 >= 0);
320 SkASSERT(arg2 >= 0);
321 if (arg1 >= 0 && arg2 <= std::numeric_limits<T>::max() - arg1) {
322 T sum = arg1 + arg2;
323 if (sum <= std::numeric_limits<size_t>::max()) {
324 *result = static_cast<size_t>(sum);
325 return true;
326 }
327 }
328 return false;
329 }
330
317 struct ICCTag { 331 struct ICCTag {
318 uint32_t fSignature; 332 uint32_t fSignature;
319 uint32_t fOffset; 333 uint32_t fOffset;
320 uint32_t fLength; 334 uint32_t fLength;
321 335
322 const uint8_t* init(const uint8_t* src) { 336 const uint8_t* init(const uint8_t* src) {
323 fSignature = read_big_endian_uint(src); 337 fSignature = read_big_endian_uint(src);
324 fOffset = read_big_endian_uint(src + 4); 338 fOffset = read_big_endian_uint(src + 4);
325 fLength = read_big_endian_uint(src + 8); 339 fLength = read_big_endian_uint(src + 8);
326 return src + 12; 340 return src + 12;
327 } 341 }
328 342
329 bool valid(size_t len) { 343 bool valid(size_t len) {
330 return_if_false(fOffset + fLength <= len, "Tag too large for ICC profile "); 344 size_t tagEnd;
345 return_if_false(safe_add(fOffset, fLength, &tagEnd),
346 "Tag too large, overflows integer addition");
347 return_if_false(tagEnd <= len, "Tag too large for ICC profile");
331 return true; 348 return true;
332 } 349 }
333 350
334 const uint8_t* addr(const uint8_t* src) const { 351 const uint8_t* addr(const uint8_t* src) const {
335 return src + fOffset; 352 return src + fOffset;
336 } 353 }
337 354
338 static const ICCTag* Find(const ICCTag tags[], int count, uint32_t signature ) { 355 static const ICCTag* Find(const ICCTag tags[], int count, uint32_t signature ) {
339 for (int i = 0; i < count; ++i) { 356 for (int i = 0; i < count; ++i) {
340 if (tags[i].fSignature == signature) { 357 if (tags[i].fSignature == signature) {
(...skipping 18 matching lines...) Expand all
359 return false; 376 return false;
360 } 377 }
361 378
362 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); 379 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8));
363 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); 380 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12));
364 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); 381 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16));
365 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); 382 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]);
366 return true; 383 return true;
367 } 384 }
368 385
369 template <class T>
370 static bool safe_add(T arg1, T arg2, size_t* result) {
371 SkASSERT(arg1 >= 0);
372 SkASSERT(arg2 >= 0);
373 if (arg1 >= 0 && arg2 <= std::numeric_limits<T>::max() - arg1) {
374 T sum = arg1 + arg2;
375 if (sum <= std::numeric_limits<size_t>::max()) {
376 *result = static_cast<size_t>(sum);
377 return true;
378 }
379 }
380 return false;
381 }
382
383 static constexpr uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', ' v'); 386 static constexpr uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', ' v');
384 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', ' a'); 387 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', ' a');
385 388
386 bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s ize_t len) { 389 bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s ize_t len) {
387 for (uint32_t i = 0; i < numGammas; i++) { 390 for (uint32_t i = 0; i < numGammas; i++) {
388 if (len < 12) { 391 if (len < 12) {
389 // FIXME (msarett): 392 // FIXME (msarett):
390 // We could potentially return false here after correctly parsing *s ome* of the 393 // We could potentially return false here after correctly parsing *s ome* of the
391 // gammas correctly. Should we somehow try to indicate a partial su ccess? 394 // gammas correctly. Should we somehow try to indicate a partial su ccess?
392 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); 395 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
801 if (0 != offsetToMatrix && offsetToMatrix < len) { 804 if (0 != offsetToMatrix && offsetToMatrix < len) {
802 if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) { 805 if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) {
803 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); 806 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n");
804 } 807 }
805 } 808 }
806 809
807 return true; 810 return true;
808 } 811 }
809 812
810 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { 813 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) {
811 if (len < kICCHeaderSize) { 814 if (!input || len < kICCHeaderSize) {
812 return_null("Data is not large enough to contain an ICC profile"); 815 return_null("Data is null or not large enough to contain an ICC profile" );
813 } 816 }
814 817
815 // Create our own copy of the input. 818 // Create our own copy of the input.
816 void* memory = sk_malloc_throw(len); 819 void* memory = sk_malloc_throw(len);
817 memcpy(memory, input, len); 820 memcpy(memory, input, len);
818 sk_sp<SkData> data = SkData::MakeFromMalloc(memory, len); 821 sk_sp<SkData> data = SkData::MakeFromMalloc(memory, len);
819 const void* base = data->data(); 822 const void* base = data->data();
820 const uint8_t* ptr = (const uint8_t*) base; 823 const uint8_t* ptr = (const uint8_t*) base;
821 824
822 // Read the ICC profile header and check to make sure that it is valid. 825 // Read the ICC profile header and check to make sure that it is valid.
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 ptr32[4] = SkEndian_SwapBE32(0x000116cc); 1141 ptr32[4] = SkEndian_SwapBE32(0x000116cc);
1139 ptr += kTAG_XYZ_Bytes; 1142 ptr += kTAG_XYZ_Bytes;
1140 1143
1141 // Write copyright tag 1144 // Write copyright tag
1142 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); 1145 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag));
1143 1146
1144 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if 1147 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if
1145 // the client calls again? 1148 // the client calls again?
1146 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); 1149 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize);
1147 } 1150 }
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