diff options
author | msarett <msarett@google.com> | 2016-06-06 10:42:51 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-06-06 10:42:51 -0700 |
commit | a4fa4f6eb727e8b97f6d8a58d9fda4aea56bbc75 (patch) | |
tree | cea2b6a233bb2dc5511f3a20e350f412da64bf5d | |
parent | 09f5cd44ae30f7089cde0131a3d07abf4c47af67 (diff) |
Gamma sanity checks
(1) Make load_gammas() return false on invalid gammas.
(2) Assert that gamma always exists after loading.
(3) Avoid dividing by zero.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2043803002
Review-Url: https://codereview.chromium.org/2043803002
-rw-r--r-- | src/core/SkColorSpace.cpp | 36 | ||||
-rw-r--r-- | src/core/SkColorSpace_Base.h | 6 |
2 files changed, 39 insertions, 3 deletions
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp index 3a81d276a8..1652de37a8 100644 --- a/src/core/SkColorSpace.cpp +++ b/src/core/SkColorSpace.cpp @@ -427,6 +427,10 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s // The table entry is the gamma (with a bias of 256). uint16_t value = read_big_endian_short((const uint8_t*) table); gammas[i].fValue = value / 256.0f; + if (0.0f == gammas[i].fValue) { + SkColorSpacePrintf("Cannot have zero gamma value"); + return false; + } SkColorSpacePrintf("gamma %d %g\n", value, gammas[i].fValue); break; } @@ -525,6 +529,10 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s // Y = 0 otherwise g = SkFixedToFloat(read_big_endian_int(src + 12)); a = SkFixedToFloat(read_big_endian_int(src + 16)); + if (0.0f == a) { + return false; + } + b = SkFixedToFloat(read_big_endian_int(src + 20)); d = -b / a; break; @@ -540,6 +548,10 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s // Y = c otherwise g = SkFixedToFloat(read_big_endian_int(src + 12)); a = SkFixedToFloat(read_big_endian_int(src + 16)); + if (0.0f == a) { + return false; + } + b = SkFixedToFloat(read_big_endian_int(src + 20)); c = SkFixedToFloat(read_big_endian_int(src + 24)); d = -b / a; @@ -594,6 +606,27 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s color_space_almost_equal(2.4000f, g)) { gammas[i].fValue = 2.2f; } else { + // Fail on invalid gammas. + if (d <= 0.0f) { + // Y = (aX + b)^g + c for always + if (0.0f == a || 0.0f == g) { + SkColorSpacePrintf("A or G is zero, constant gamma function " + "is nonsense"); + return false; + } + } else if (d >= 1.0f) { + // Y = eX + f for always + if (0.0f == e) { + SkColorSpacePrintf("E is zero, constant gamma function is " + "nonsense"); + return false; + } + } else if ((0.0f == a || 0.0f == g) && 0.0f == e) { + SkColorSpacePrintf("A or G, and E are zero, constant gamma function " + "is nonsense"); + return false; + } + gammas[i].fG = g; gammas[i].fA = a; gammas[i].fB = b; @@ -611,6 +644,9 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s return false; } + // Ensure that we have successfully read a gamma representation. + SkASSERT(gammas[i].isValue() || gammas[i].isTable() || gammas[i].isParametric()); + // Adjust src and len if there is another gamma curve to load. if (i != numGammas - 1) { // Each curve is padded to 4-byte alignment. diff --git a/src/core/SkColorSpace_Base.h b/src/core/SkColorSpace_Base.h index b2d5818e84..68514d0ad6 100644 --- a/src/core/SkColorSpace_Base.h +++ b/src/core/SkColorSpace_Base.h @@ -16,20 +16,20 @@ struct SkGammaCurve { bool isValue() const { bool result = (0.0f != fValue); SkASSERT(!result || (0 == fTableSize)); - SkASSERT(!result || (0.0f == fG)); + SkASSERT(!result || (0.0f == fG && 0.0f == fE)); return result; } bool isTable() const { bool result = (0 != fTableSize); SkASSERT(!result || (0.0f == fValue)); - SkASSERT(!result || (0.0f == fG)); + SkASSERT(!result || (0.0f == fG && 0.0f == fE)); SkASSERT(!result || fTable); return result; } bool isParametric() const { - bool result = (0.0f != fG); + bool result = (0.0f != fG || 0.0f != fE); SkASSERT(!result || (0.0f == fValue)); SkASSERT(!result || (0 == fTableSize)); return result; |