Coverage Report

Created: 2023-03-26 06:45

/src/cms_transform_extended_fuzzer.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright 2022 Google LLC
2
Licensed under the Apache License, Version 2.0 (the "License");
3
you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5
      http://www.apache.org/licenses/LICENSE-2.0
6
Unless required by applicable law or agreed to in writing, software
7
distributed under the License is distributed on an "AS IS" BASIS,
8
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
See the License for the specific language governing permissions and
10
limitations under the License.
11
*/
12
13
#include <stdint.h>
14
#include "lcms2.h"
15
16
// An extended cmsDoTransform fuzzer. The idea is to include a range of
17
// input/output source formats.
18
19
void
20
run_test(const uint8_t *data,
21
         size_t size,
22
         uint32_t intent,
23
6.10k
         uint32_t flags, int dstVal) {
24
6.10k
  if (size < 2) {
25
2
    return;
26
2
  }
27
28
6.09k
  cmsHPROFILE srcProfile = cmsOpenProfileFromMem(data, size);
29
6.09k
  if (!srcProfile) return;
30
31
  // Select dstProfile and dstFormat
32
5.38k
  cmsHPROFILE dstProfile;
33
5.38k
  uint32_t dstFormat;
34
5.38k
  if (dstVal == 1) {
35
448
    dstProfile = cmsCreateLab4Profile(NULL);
36
448
    dstFormat = TYPE_Lab_8;
37
448
  }
38
4.93k
  else if (dstVal == 2) {
39
1.17k
    dstProfile = cmsCreateLab2Profile(NULL);
40
1.17k
    dstFormat = TYPE_LabV2_8;
41
1.17k
  }
42
3.76k
  else if (dstVal == 3) {
43
291
    cmsToneCurve* gamma18;
44
291
    gamma18 = cmsBuildGamma(0, 1.8);
45
291
    dstProfile = cmsCreateGrayProfile(NULL, gamma18);
46
291
    cmsFreeToneCurve(gamma18);
47
291
    dstFormat = TYPE_GRAY_FLT | EXTRA_SH(1);
48
291
  }
49
3.47k
  else if (dstVal == 4) {
50
662
    dstProfile = cmsCreateXYZProfile();
51
662
    dstFormat = TYPE_XYZ_16;
52
662
  }
53
2.80k
  else if (dstVal == 5) {
54
368
    dstProfile = cmsCreateXYZProfile();
55
368
    dstFormat = TYPE_XYZ_DBL;
56
368
  }
57
2.44k
  else if (dstVal == 6) {
58
624
    dstProfile = cmsCreateLab4Profile(NULL);
59
624
    dstFormat = TYPE_Lab_DBL;
60
624
  }
61
1.81k
  else if (dstVal == 7) {
62
228
    dstProfile = cmsCreateLab4Profile(NULL);
63
228
    dstFormat = TYPE_Lab_DBL;
64
228
  }
65
1.58k
  else {
66
1.58k
    dstProfile = cmsCreate_sRGBProfile();
67
1.58k
    dstFormat = TYPE_RGB_8;
68
1.58k
  }
69
70
5.38k
  if (!dstProfile) {
71
0
    cmsCloseProfile(srcProfile);
72
0
    return;
73
0
  }
74
75
  // Extract srcFormat from the random src profile
76
5.38k
  cmsColorSpaceSignature srcCS = cmsGetColorSpace(srcProfile);
77
5.38k
  cmsUInt32Number nSrcComponents = cmsChannelsOf(srcCS);
78
5.38k
  cmsUInt32Number srcFormat;
79
5.38k
  if (srcCS == cmsSigLabData) {
80
341
    if (dstVal != 7) {
81
325
        srcFormat =
82
325
            COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0);
83
325
    }
84
16
    else {
85
16
        srcFormat =
86
16
            COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0) | FLOAT_SH(1);
87
16
    }
88
5.04k
  } else {
89
5.04k
    srcFormat =
90
5.04k
        COLORSPACE_SH(PT_ANY) | CHANNELS_SH(nSrcComponents) | BYTES_SH(1);
91
5.04k
  }
92
93
  // Create the transform
94
5.38k
  cmsContext ctx = cmsCreateContext(NULL, NULL);
95
5.38k
  cmsHTRANSFORM hTransform = cmsCreateTransformTHR(
96
5.38k
    ctx,
97
5.38k
    srcProfile,
98
5.38k
    srcFormat,
99
5.38k
    dstProfile,
100
5.38k
    dstFormat,
101
5.38k
    intent,
102
5.38k
    flags);
103
104
5.38k
  cmsCloseProfile(srcProfile);
105
5.38k
  cmsCloseProfile(dstProfile);
106
5.38k
  if (!hTransform) return;
107
108
109
  // Do transformation.
110
  // The output buffer type depends on the dstFormat
111
  // The input buffer type depends on the srcFormat.
112
906
  if (T_BYTES(srcFormat) == 0) {  // 0 means double
113
    // Ensure output is large enough
114
8
    long long output[nSrcComponents*4];
115
8
    double input[nSrcComponents];
116
32
    for (uint32_t i = 0; i < nSrcComponents; i++) input[i] = 0.5f;
117
8
    cmsDoTransform(hTransform, input, output, 1);
118
8
  } 
119
898
  else {
120
898
    uint8_t input[nSrcComponents];
121
3.95k
    for (uint32_t i = 0; i < nSrcComponents; i++) input[i] = 128;
122
123
898
    if (dstFormat == TYPE_XYZ_16) {
124
94
      cmsCIEXYZ output_XYZ = { 0, 0, 0 };
125
94
      cmsDoTransform(hTransform, input, &output_XYZ, 1);
126
94
    }
127
804
    else if (dstFormat == TYPE_XYZ_DBL) {
128
31
      cmsCIEXYZTRIPLE out[4];
129
31
      cmsDoTransform(hTransform, input, out, 1);
130
31
    }
131
773
    else if (dstFormat == TYPE_Lab_DBL) {
132
91
      cmsCIELab Lab1;
133
91
      cmsDoTransform(hTransform, input, &Lab1, 1);
134
91
    }
135
682
    else {
136
682
      uint8_t output[4];
137
682
      cmsDoTransform(hTransform, input, output, 1);
138
682
    }
139
898
  }
140
906
  cmsDeleteTransform(hTransform);
141
906
}
142
143
144
14.2k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
145
14.2k
  if (size < 12) {
146
12
    return 0;
147
12
  }
148
149
14.2k
  uint32_t flags         = *((const uint32_t *)data+0);
150
14.2k
  uint32_t intent        = *((const uint32_t *)data+1) % 16;
151
14.2k
  int decider = *((int*)data+2) % 10;
152
14.2k
  data += 12;
153
14.2k
  size -= 12;
154
155
  // Transform using various output formats.
156
14.2k
  run_test(data, size, intent, flags, decider);
157
158
14.2k
  return 0;
159
14.2k
}