Improve testing coverage of new code and fix bugs that it found.
diff --git a/Makefile b/Makefile
index ebdb147..ce119b7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-#COVERAGE_FLAGS=-fprofile-arcs -ftest-coverage
+COVERAGE_FLAGS=-fprofile-arcs -ftest-coverage
#COVERAGE_FLAGS=
OPT_FLAGS=-O0
OPT_FLAGS=
@@ -15,5 +15,10 @@
$(PROGRAMS): $(QCMS_OBJS)
+gen-coverage:
+ mkdir -p lcov
+ lcov -d . -c --output-file lcov/lcov.info
+ genhtml -o lcov/ lcov/lcov.info
+
clean:
rm -f $(PROGRAMS) $(QCMS_OBJS)
diff --git a/iccread.c b/iccread.c
index 2e4a645..e1c9c9a 100644
--- a/iccread.c
+++ b/iccread.c
@@ -674,6 +674,7 @@
num_output_table_entries = read_u16(src, offset + 50);
entry_size = 2;
} else {
+ assert(0); // the caller checks that this doesn't happen
invalid_source(src, "Unexpected lut type");
return NULL;
}
@@ -727,9 +728,9 @@
clut_offset = offset + 52 + lut->num_input_table_entries * in_chan * entry_size;
for (i = 0; i < clut_size * out_chan; i+=3) {
if (type == LUT8_TYPE) {
- lut->clut_table[i*3+0] = uInt8Number_to_float(read_uInt8Number(src, clut_offset + i*entry_size + 0));
- lut->clut_table[i*3+1] = uInt8Number_to_float(read_uInt8Number(src, clut_offset + i*entry_size + 1));
- lut->clut_table[i*3+2] = uInt8Number_to_float(read_uInt8Number(src, clut_offset + i*entry_size + 2));
+ lut->clut_table[i+0] = uInt8Number_to_float(read_uInt8Number(src, clut_offset + i*entry_size + 0));
+ lut->clut_table[i+1] = uInt8Number_to_float(read_uInt8Number(src, clut_offset + i*entry_size + 1));
+ lut->clut_table[i+2] = uInt8Number_to_float(read_uInt8Number(src, clut_offset + i*entry_size + 2));
} else {
lut->clut_table[i+0] = uInt16Number_to_float(read_uInt16Number(src, clut_offset + i*entry_size + 0));
lut->clut_table[i+1] = uInt16Number_to_float(read_uInt16Number(src, clut_offset + i*entry_size + 2));
@@ -1045,8 +1046,8 @@
}
}
if (find_tag(index, TAG_B2A0)) {
- if (read_u32(src, find_tag(index, TAG_A2B0)->offset) == LUT8_TYPE ||
- read_u32(src, find_tag(index, TAG_A2B0)->offset) == LUT16_TYPE) {
+ if (read_u32(src, find_tag(index, TAG_B2A0)->offset) == LUT8_TYPE ||
+ read_u32(src, find_tag(index, TAG_B2A0)->offset) == LUT16_TYPE) {
profile->B2A0 = read_tag_lutType(src, index, TAG_B2A0);
} else if (read_u32(src, find_tag(index, TAG_B2A0)->offset) == LUT_MBA_TYPE) {
profile->mBA = read_tag_lutmABType(src, index, TAG_B2A0);
@@ -1076,6 +1077,7 @@
goto invalid_tag_table;
} else {
+ assert(0 && "read_color_space protects against entering here");
goto invalid_tag_table;
}
} else {
diff --git a/invalid-coverage.c b/invalid-coverage.c
index da82b11..b96df73 100644
--- a/invalid-coverage.c
+++ b/invalid-coverage.c
@@ -38,58 +38,66 @@
{
*(uint8_t*)(buf + offset) = value;
}
+static void write_u16(size_t offset, uint16_t value)
+{
+ *(uint8_t*)(buf + offset + 1) = value & 0xff;
+ *(uint8_t*)(buf + offset) = (value>>8) & 0xff;
+}
+#define PROFILE_LENGTH 18000
int main()
{
qcms_profile_release(qcms_profile_sRGB());
- buf = calloc(1500, 1);
- assert(!qcms_profile_from_memory(buf, 1500));
+ buf = calloc(PROFILE_LENGTH, 1);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
// invalid size
- write_u32(0, 2500);
- assert(!qcms_profile_from_memory(buf, 1500));
+ write_u32(0, PROFILE_LENGTH + 2500);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
// proper size
- write_u32(0, 1500);
- assert(!qcms_profile_from_memory(buf, 1500));
+ write_u32(0, PROFILE_LENGTH);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
#define INPUT_DEVICE_PROFILE 0x73636e72 // 'scnr'
write_u32(12, INPUT_DEVICE_PROFILE);
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u8(8, 0x3); // invalid major revision
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u8(8, 0x2); // major revision
write_u8(9, 0x55); // invalid minor revision
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u8(8, 0x2); // major revision
write_u8(9, 0x40); // minor revision
write_u8(10, 1); // reserved 1
write_u8(11, 0); // reserved 2
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u8(10, 0); // reserved 1
write_u8(64, 0x32); // invalid rendering intent
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u8(64, 0); // invalid rendering intent
#define RGB_SIGNATURE 0x52474220
#define GRAY_SIGNATURE 0x47524159
- write_u32(16, RGB_SIGNATURE);
- assert(!qcms_profile_from_memory(buf, 1500));
+ write_u32(16, 0xdeadbeef);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u32(16, RGB_SIGNATURE);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
#define XYZ_SIGNATURE 0x58595A20
write_u32(20, XYZ_SIGNATURE);
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128, 15000); // tag count
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128, 15); // tag count
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
#define TAG_bXYZ 0x6258595a
#define TAG_gXYZ 0x6758595a
@@ -99,67 +107,202 @@
#define TAG_gTRC 0x67545243
#define TAG_kTRC 0x6b545243
#define TAG_A2B0 0x41324230
+ #define TAG_B2A0 0x42324130
+ #define TAG_CHAD 0x63686164
write_u32(128 + 4, TAG_rXYZ); // tag
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128 + 4 + 4, 1000); // offset
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128 + 4 + 4*1*3, TAG_gXYZ); // tag
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128 + 4 + 4*1*3 + 4, 1000); // offset
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128 + 4 + 4*2*3, TAG_bXYZ); // tag
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128 + 4 + 4*2*3 + 4, 1000); // offset
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
#define XYZ_TYPE 0x58595a20 // 'XYZ '
#define CURVE_TYPE 0x63757276 // 'curv'
#define LUT16_TYPE 0x6d667432 // 'mft2'
#define LUT8_TYPE 0x6d667431 // 'mft1'
-
+#define LUT_MAB_TYPE 0x6d414220 // 'mAB '
+#define LUT_MBA_TYPE 0x6d424120 // 'mBA '
+#define CHROMATIC_TYPE 0x73663332 // 'sf32'
+#define PARAMETRIC_CURVE_TYPE 0x70617261 // 'para'
write_u32(1000, XYZ_TYPE);
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128 + 4 + 4*3*3, TAG_rTRC); // tag
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128 + 4 + 4*3*3 + 4, 1100); // offset
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128 + 4 + 4*4*3, TAG_gTRC); // tag
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128 + 4 + 4*4*3 + 4, 1100); // offset
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128 + 4 + 4*5*3, TAG_bTRC); // tag
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(128 + 4 + 4*5*3 + 4, 1100); // offset
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(128 + 4 + 4*6*3, TAG_A2B0); // tag
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(128 + 4 + 4*6*3 + 4, 1200); // offset
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(128 + 4 + 4*7*3, TAG_CHAD); // tag
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u32(128 + 4 + 4*7*3 + 4, 5000); // offset
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(1200, 5); // invalid lut type
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(1200, LUT8_TYPE);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u8(1200 + 8, 9); // max clut size
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u8(1200 + 10, 9); // max clut size
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u8(1200 + 8, 3); // in_chan
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u8(1200 + 9, 3); // proper out_chan
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u8(1200 + 10, 1); // sane clut size
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(1200, LUT16_TYPE);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u16(1200 + 48, 3); // input_table_entries
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u16(1200 + 50, 3); // output_table_entries
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(128 + 4 + 4*6*3, TAG_A2B0); // tag
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(128 + 4 + 4*6*3, TAG_B2A0); // tag
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(1200, LUT_MBA_TYPE);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(1200, LUT_MAB_TYPE);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(128 + 4 + 4*6*3, TAG_A2B0); // tag
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u8(1200 + 8, 15); // > max in_chan
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u8(1200 + 9, 15); // > max out_chan
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u8(1200 + 9, 4); // long out_chan
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u8(1200 + 8, 2); // short in_chan
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u8(1200 + 9, 3); // proper out_chan
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u8(1200 + 8, 3); // proper out_chan
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u32(1200 + 12, 5); // b curve offset
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(1200 + 12, 2000); // b curve offset
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(1200 + 16, 2000); // matrix offset
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(1200 + 20, 2000); // m curve offset
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(1200 + 24, 3000); // clut offset
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u8(4200, 255); // clut channel size
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u8(4201, 255); // clut channel size
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u8(4202, 255); // clut channel size
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u8(4200, 2); // clut channel size
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u8(4201, 2); // clut channel size
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u8(4202, 2); // clut channel size
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u8(4216, 1); // clut precision
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u8(4216, 2); // clut precision
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(1200 + 28, 2000); // a curve offset
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(3200, PARAMETRIC_CURVE_TYPE);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u16(3208, 5);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u16(3208, 4);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u16(3208, 2);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(3200, CURVE_TYPE);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ // reset the values
+ write_u16(3208, 0);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+
+ write_u32(3212, CURVE_TYPE);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u32(3224, CURVE_TYPE);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+
+ write_u32(5000, CHROMATIC_TYPE);
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+#if 1
write_u32(1100, CURVE_TYPE);
- qcms_profile_release(qcms_profile_from_memory(buf, 1500));
+ qcms_profile_release(qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(1108, 100000); // curve count
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
write_u32(1108, 1); // curve count
- qcms_profile_release(qcms_profile_from_memory(buf, 1500));
+ qcms_profile_release(qcms_profile_from_memory(buf, PROFILE_LENGTH));
/* test out gray profiles */
write_u32(16, GRAY_SIGNATURE);
- assert(!qcms_profile_from_memory(buf, 1500));
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
- write_u32(128 + 4 + 4*6*3, TAG_kTRC); // tag
- assert(!qcms_profile_from_memory(buf, 1500));
- write_u32(128 + 4 + 4*6*3 + 4, 1100); // offset
- qcms_profile_release(qcms_profile_from_memory(buf, 1500));
+ write_u32(128 + 4 + 4*8*3, TAG_kTRC); // tag
+ assert(!qcms_profile_from_memory(buf, PROFILE_LENGTH));
+ write_u32(128 + 4 + 4*8*3 + 4, 1100); // offset
+ qcms_profile_release(qcms_profile_from_memory(buf, PROFILE_LENGTH));
/* test out profiles that are the wrong size */
qcms_profile_from_path("sample-trunc.icc");
-
+#endif
return 0;
}
diff --git a/malloc-fail.c b/malloc-fail.c
index ed93b1e..9554aa4 100644
--- a/malloc-fail.c
+++ b/malloc-fail.c
@@ -78,9 +78,13 @@
unsigned char outt[4];
qcms_transform *transform;
qcms_profile *input_profile, *output_profile, *rgb;
- qcms_CIE_xyY white_point = { 0, 0, 1.};
+ qcms_CIE_xyY invalid_white_point = { 0., 0., 1.};
+ qcms_CIE_xyY white_point = { 0.9, 1., 1.};
qcms_CIE_xyYTRIPLE primaries = { {.9, .3, 1.}, {.2, .4, 1.}, {.7, .4, 1.}};
+ rgb = qcms_profile_create_rgb_with_gamma(invalid_white_point, primaries, 1.8);
+ if (rgb)
+ qcms_profile_release(rgb);
rgb = qcms_profile_create_rgb_with_gamma(white_point, primaries, 1.8);
input_profile = qcms_profile_sRGB();
output_profile = qcms_profile_sRGB();