[babl] babl: proof icc parsing against corrupt data
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [babl] babl: proof icc parsing against corrupt data
- Date: Sat, 19 Aug 2017 21:43:53 +0000 (UTC)
commit dafec35ec5815c6319d3b5ad7f10616857cc694c
Author: Øyvind Kolås <pippin gimp org>
Date: Sat Aug 19 23:43:32 2017 +0200
babl: proof icc parsing against corrupt data
babl/babl-icc.c | 224 ++++++++++++++++++++++++++++++------------------------
1 files changed, 124 insertions(+), 100 deletions(-)
---
diff --git a/babl/babl-icc.c b/babl/babl-icc.c
index 7fd9b32..129368b 100644
--- a/babl/babl-icc.c
+++ b/babl/babl-icc.c
@@ -1,3 +1,21 @@
+/* babl - dynamically extendable universal pixel conversion library.
+ * Copyright (C) 2017, Øyvind Kolås.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
#include "config.h"
#include "babl-internal.h"
#include <stdio.h>
@@ -6,80 +24,85 @@
#define ICC_HEADER_LEN 128
#define TAG_COUNT_OFF ICC_HEADER_LEN
-static int load_byte (const char *icc, int offset)
+static int load_byte (const char *icc, int length, int offset)
{
+/* all reading functions take both the char *pointer and the length of the
+ * buffer, and all reads thus gets protected by this condition.
+ */
+ if (offset < 0 || offset > length)
+ return 0;
+
return *(uint8_t*) (&icc[offset]);
}
-static int16_t load_u1Fixed15 (const char *icc, int offset)
+static int load_sbyte (const char *icc, int length, int offset)
+{
+ if (offset < 0 || offset > length)
+ return 0;
+
+ return *(int8_t*) (&icc[offset]);
+}
+
+static int16_t load_u1f15 (const char *icc, int length, int offset)
{
- return load_byte (icc, offset + 1) +
- (load_byte (icc, offset + 0) << 8);
+ return load_sbyte (icc, length, offset + 1) +
+ (load_byte (icc, length, offset + 0) << 8);
}
-static uint16_t load_uint16 (const char *icc, int offset)
+static uint16_t load_u16 (const char *icc, int length, int offset)
{
- return load_byte (icc, offset + 1) +
- (load_byte (icc, offset + 0) << 8);
+ return load_byte (icc, length, offset + 1) +
+ (load_byte (icc, length, offset + 0) << 8);
}
-static double load_s15Fixed16 (const char *icc, int offset)
+static double load_s15f15 (const char *icc, int length, int offset)
{
- return load_u1Fixed15 (icc, offset) + load_uint16 (icc, offset + 2) / 65535.0f;
+ return load_u1f15 (icc, length, offset) +
+ load_u16 (icc, length, offset + 2) / 65535.0f;
}
-static double load_u16Fixed16 (const char *icc, int offset)
+static double load_u16f16 (const char *icc, int length, int offset)
{
- return load_uint16 (icc, offset) + load_uint16 (icc, offset + 2) / 65535.0;
+ return load_u16 (icc, length, offset) +
+ load_u16 (icc, length, offset + 2) / 65535.0;
}
-static uint32_t load_uint32 (const char *icc, int offset)
+static uint32_t load_u32 (const char *icc, int length, int offset)
{
- return load_byte (icc, offset + 3) +
- (load_byte (icc, offset + 2) << 8) +
- (load_byte (icc, offset + 1) << 16) +
- (load_byte (icc, offset + 0) << 24);
+ return load_byte (icc, length, offset + 3) +
+ (load_byte (icc, length, offset + 2) << 8) +
+ (load_byte (icc, length, offset + 1) << 16) +
+ (load_byte (icc, length, offset + 0) << 24);
}
-static void load_sign (const char *icc, int offset, char *sign)
+static void load_sign (const char *icc, int length,
+ int offset, char *sign)
{
- sign[0]=load_byte(icc, offset);
- sign[1]=load_byte(icc, offset + 1);
- sign[2]=load_byte(icc, offset + 2);
- sign[3]=load_byte(icc, offset + 3);
+ sign[0]=load_byte(icc, length, offset);
+ sign[1]=load_byte(icc, length, offset + 1);
+ sign[2]=load_byte(icc, length, offset + 2);
+ sign[3]=load_byte(icc, length, offset + 3);
sign[4]=0;
}
-/* looks up offset and length for a specifi icc tag
+/* looks up offset and length for a specific icc tag
*/
-static int icc_tag (const char *icc, const char *tag, int *offset, int *length)
+static int icc_tag (const char *icc, int length,
+ const char *tag, int *offset, int *el_length)
{
- int tag_count = load_uint32 (icc, TAG_COUNT_OFF);
- int profile_size = load_uint32 (icc, 0);
+ int tag_count = load_u32 (icc, length, TAG_COUNT_OFF);
int t;
for (t = 0; t < tag_count; t++)
{
char tag_signature[5];
- load_sign (icc, TAG_COUNT_OFF + 4 + 12 * t, tag_signature);
+ load_sign (icc, length, TAG_COUNT_OFF + 4 + 12 * t, tag_signature);
if (!strcmp (tag_signature, tag))
{
- if (!offset)
- return 1;
- *offset = load_uint32 (icc, TAG_COUNT_OFF + 4 + 12* t + 4);
- /* avert some potential for maliciousnes.. */
- if (*offset >= profile_size)
- {
- *offset = profile_size - 1;
- }
- if (!length)
- return 1;
- *length = load_uint32 (icc, TAG_COUNT_OFF + 4 + 12* t + 4 * 2);
- /* avert some potential for maliciousnes.. */
- if (*offset + *length >= profile_size)
- {
- *length = profile_size - *offset - 1;
- }
+ if (offset)
+ *offset = load_u32 (icc, length, TAG_COUNT_OFF + 4 + 12* t + 4);
+ if (el_length)
+ *el_length = load_u32 (icc, length, TAG_COUNT_OFF + 4 + 12* t + 4*2);
return 1;
}
}
@@ -92,7 +115,7 @@ static const Babl *babl_trc_from_icc (const char *icc,
{
int offset = 0;
{
- int count = load_uint32 (icc, offset + 8);
+ int count = load_u32 (icc, length, offset + 8);
int i;
{
if (count == 0)
@@ -101,8 +124,8 @@ static const Babl *babl_trc_from_icc (const char *icc,
}
else if (count == 1)
{
- return babl_trc_gamma (load_byte (icc, offset + 12) +
- load_byte (icc, offset + 12 + 1) / 255.0);
+ return babl_trc_gamma (load_byte (icc, length, offset + 12) +
+ load_byte (icc, length, offset + 12 + 1)/255.0);
}
else
{
@@ -113,9 +136,10 @@ static const Babl *babl_trc_from_icc (const char *icc,
for (i = 0; i < count && i < 10; i ++)
{
- fprintf (stdout, "%i=%i ", i, load_uint16 (icc, offset + 12 + i * 2));
+ fprintf (stdout, "%i=%i ", i, load_u16 (icc, length,
+ offset + 12 + i * 2));
if (i % 7 == 0)
- fprintf (stdout, "\n");
+ fprintf (stdout, "\n");
}
}
}
@@ -128,11 +152,11 @@ babl_space_rgb_icc (const char *icc,
int length,
char **error)
{
- int profile_size = load_uint32 (icc, 0);
- int icc_ver_major = load_byte (icc, 8);
- const Babl *trc_red = NULL;
+ int profile_size = load_u32 (icc, length, 0);
+ int icc_ver_major = load_byte (icc, length, 8);
+ const Babl *trc_red = NULL;
const Babl *trc_green = NULL;
- const Babl *trc_blue = NULL;
+ const Babl *trc_blue = NULL;
char profile_class[5];
char color_space[5];
@@ -146,13 +170,13 @@ babl_space_rgb_icc (const char *icc,
*error = "only ICC v2 profiles supported";
return NULL;
}
- load_sign (icc, 12, profile_class);
+ load_sign (icc, length, 12, profile_class);
if (strcmp (profile_class, "mntr"))
{
*error = "not a monitor-class profile";
return NULL;
}
- load_sign (icc, 16, color_space);
+ load_sign (icc, length, 16, color_space);
if (strcmp (color_space, "RGB "))
{
*error = "not defining an RGB space";
@@ -160,23 +184,20 @@ babl_space_rgb_icc (const char *icc,
}
{
int offset, element_size;
- if (icc_tag (icc, "rTRC", &offset, &element_size))
+ if (icc_tag (icc, length, "rTRC", &offset, &element_size))
{
trc_red = babl_trc_from_icc (icc + offset, element_size, error);
- if (*error)
- return NULL;
+ if (*error) return NULL;
}
- if (icc_tag (icc, "gTRC", &offset, &element_size))
+ if (icc_tag (icc, length, "gTRC", &offset, &element_size))
{
trc_green = babl_trc_from_icc (icc + offset, element_size, error);
- if (*error)
- return NULL;
+ if (*error) return NULL;
}
- if (icc_tag (icc, "bTRC", &offset, &element_size))
+ if (icc_tag (icc, length, "bTRC", &offset, &element_size))
{
trc_blue = babl_trc_from_icc (icc + offset, element_size, error);
- if (*error)
- return NULL;
+ if (*error) return NULL;
}
}
@@ -186,37 +207,40 @@ babl_space_rgb_icc (const char *icc,
return NULL;
}
- if (icc_tag (icc, "chrm", NULL, NULL) &&
- icc_tag (icc, "wtpt", NULL, NULL))
+ if (icc_tag (icc, length, "chrm", NULL, NULL) &&
+ icc_tag (icc, length, "wtpt", NULL, NULL))
{
int offset, element_size;
double redX, redY, greenX, greenY, blueX, blueY;
+ int channels, phosporant;
- icc_tag (icc, "chrm", &offset, &element_size);
- {
- int channels = load_uint16 (icc, offset + 8);
- int phosporant = load_uint16 (icc, offset + 10);
-
- redX = load_s15Fixed16 (icc, offset + 12);
- redY = load_s15Fixed16 (icc, offset + 12 + 4);
- greenX = load_s15Fixed16 (icc, offset + 20);
- greenY = load_s15Fixed16 (icc, offset + 20 + 4);
- blueX = load_s15Fixed16 (icc, offset + 28);
- blueY = load_s15Fixed16 (icc, offset + 28 + 4);
+ icc_tag (icc, length, "chrm", &offset, &element_size);
+ channels = load_u16 (icc, length, offset + 8);
+ phosporant = load_u16 (icc, length, offset + 10);
- fprintf (stdout, "chromaticity:\n");
- fprintf (stdout, " channels: %i\n", channels);
- fprintf (stdout, " phosphorant: %i\n", phosporant);
- fprintf (stdout, " CIE xy red: %f %f\n", redX, redY);
- fprintf (stdout, " CIE xy green: %f %f\n", greenX, greenY);
- fprintf (stdout, " CIE xy blue: %f %f\n", blueX, blueY);
+ if (phosporant != 0)
+ {
+ *error = "unhandled phosporants, please report bug";
+ return NULL;
}
+ if (channels != 3)
+ {
+ *error = "unexpected non 3 count of channels";
+ return NULL;
+ }
+
+ redX = load_s15f15 (icc, length, offset + 12);
+ redY = load_s15f15 (icc, length, offset + 12 + 4);
+ greenX = load_s15f15 (icc, length, offset + 20);
+ greenY = load_s15f15 (icc, length, offset + 20 + 4);
+ blueX = load_s15f15 (icc, length, offset + 28);
+ blueY = load_s15f15 (icc, length, offset + 28 + 4);
- icc_tag (icc, "wtpt", &offset, &element_size);
+ icc_tag (icc, length, "wtpt", &offset, &element_size);
{
- double wX = load_u16Fixed16 (icc, offset + 8);
- double wY = load_u16Fixed16 (icc, offset + 8 + 4);
- double wZ = load_u16Fixed16 (icc, offset + 8 + 4 * 2);
+ double wX = load_u16f16 (icc, length, offset + 8);
+ double wY = load_u16f16 (icc, length, offset + 8 + 4);
+ double wZ = load_u16f16 (icc, length, offset + 8 + 4 * 2);
return babl_space_rgb_chromaticities (NULL,
wX / (wX + wY + wZ),
@@ -228,27 +252,27 @@ babl_space_rgb_icc (const char *icc,
}
}
- else if (icc_tag (icc, "rXYZ", NULL, NULL) &&
- icc_tag (icc, "gXYZ", NULL, NULL) &&
- icc_tag (icc, "bXYZ", NULL, NULL))
+ else if (icc_tag (icc, length, "rXYZ", NULL, NULL) &&
+ icc_tag (icc, length, "gXYZ", NULL, NULL) &&
+ icc_tag (icc, length, "bXYZ", NULL, NULL))
{
int offset, element_size;
double rx, gx, bx;
double ry, gy, by;
double rz, gz, bz;
- icc_tag (icc, "rXYZ", &offset, &element_size);
- rx = load_u16Fixed16 (icc, offset + 8 + 4 * 0);
- ry = load_u16Fixed16 (icc, offset + 8 + 4 * 1);
- rz = load_u16Fixed16 (icc, offset + 8 + 4 * 2);
- icc_tag (icc, "gXYZ", &offset, &element_size);
- gx = load_u16Fixed16 (icc, offset + 8 + 4 * 0);
- gy = load_u16Fixed16 (icc, offset + 8 + 4 * 1);
- gz = load_u16Fixed16 (icc, offset + 8 + 4 * 2);
- icc_tag (icc, "bXYZ", &offset, &element_size);
- bx = load_u16Fixed16 (icc, offset + 8 + 4 * 0);
- by = load_u16Fixed16 (icc, offset + 8 + 4 * 1);
- bz = load_u16Fixed16 (icc, offset + 8 + 4 * 2);
+ icc_tag (icc, length, "rXYZ", &offset, &element_size);
+ rx = load_u16f16 (icc, length, offset + 8 + 4 * 0);
+ ry = load_u16f16 (icc, length, offset + 8 + 4 * 1);
+ rz = load_u16f16 (icc, length, offset + 8 + 4 * 2);
+ icc_tag (icc, length, "gXYZ", &offset, &element_size);
+ gx = load_u16f16 (icc, length, offset + 8 + 4 * 0);
+ gy = load_u16f16 (icc, length, offset + 8 + 4 * 1);
+ gz = load_u16f16 (icc, length, offset + 8 + 4 * 2);
+ icc_tag (icc, length, "bXYZ", &offset, &element_size);
+ bx = load_u16f16 (icc, length, offset + 8 + 4 * 0);
+ by = load_u16f16 (icc, length, offset + 8 + 4 * 1);
+ bz = load_u16f16 (icc, length, offset + 8 + 4 * 2);
return babl_space_rgb_matrix (NULL,
rx, gx, bx,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]