summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Alexander Steffens (heftig) <jan.steffens@gmail.com>2017-12-16 04:18:01 +0100
committerRichard Hughes <richard@hughsie.com>2018-03-27 10:26:33 +0100
commitba4bdb6f0dadc8f2d51122bfdee9a0325302f171 (patch)
treec27e3fe00d9e88f336c46d7cc5943c0583bbd096
parent6a16dad69dd11f07f4a9fea9a94901df36665018 (diff)
downloadcolord-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.c27
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;
}