diff options
author | Jan Alexander Steffens (heftig) <jan.steffens@gmail.com> | 2017-12-16 04:18:01 +0100 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2018-03-27 10:26:33 +0100 |
commit | ba4bdb6f0dadc8f2d51122bfdee9a0325302f171 (patch) | |
tree | c27e3fe00d9e88f336c46d7cc5943c0583bbd096 | |
parent | 6a16dad69dd11f07f4a9fea9a94901df36665018 (diff) | |
download | colord-ba4bdb6f0dadc8f2d51122bfdee9a0325302f171.tar.gz |
Make cd_color_get_blackbody_rgb_full safer
Validate arguments:
- temp == NaN would fail the bounds checks and could result in
out-of-bounds reads.
- result == NULL is an obvious error.
Avoid calling cd_color_rgb_interpolate if the second point would be
outside the data array. This only happens for temp == 10000, which makes
the alpha 0, so one would think that the garbage read has no effect on
the result. However, if the garbage happens to contain NaNs they would
propagate to the output. Besides, asan and valgrind still complain.
-rw-r--r-- | lib/colord/cd-color.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/lib/colord/cd-color.c b/lib/colord/cd-color.c index 6062595..7eee9aa 100644 --- a/lib/colord/cd-color.c +++ b/lib/colord/cd-color.c @@ -1444,10 +1444,12 @@ cd_color_get_blackbody_rgb_full (gdouble temp, CdColorBlackbodyFlags flags) { gboolean ret = TRUE; - gdouble alpha; - gint temp_index; + guint temp_quot, temp_rem; const CdColorRGB *blackbody_func = blackbody_data_d65modified; + g_return_val_if_fail (!isnan (temp), FALSE); + g_return_val_if_fail (result != NULL, FALSE); + /* use modified curve */ if (flags & CD_COLOR_BLACKBODY_FLAG_USE_PLANCKIAN) blackbody_func = blackbody_data_d65plankian; @@ -1464,12 +1466,23 @@ cd_color_get_blackbody_rgb_full (gdouble temp, temp = 10000; } + /* blackbody data has a resolution of 100 K */ + temp_quot = (guint) temp / 100; + temp_rem = (guint) temp % 100; + + /* blackbody data starts at 1000 K */ + temp_quot -= 10; + + if (temp_rem == 0) { + /* exact match for data point */ + *result = blackbody_func[temp_quot]; + return ret; + } + /* bilinear interpolate the blackbody data */ - alpha = ((guint) temp % 100) / 100.0; - temp_index = ((guint) temp - 1000) / 100; - cd_color_rgb_interpolate (&blackbody_func[temp_index], - &blackbody_func[temp_index + 1], - alpha, + cd_color_rgb_interpolate (&blackbody_func[temp_quot], + &blackbody_func[temp_quot + 1], + temp_rem / 100.0, result); return ret; } |