Coverage Report

Created: 2023-09-25 06:26

/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
5.75k
         uint32_t flags, int dstVal) {
24
5.75k
  if (size < 2) {
25
2
    return;
26
2
  }
27
28
5.75k
  cmsHPROFILE srcProfile = cmsOpenProfileFromMem(data, size);
29
5.75k
  if (!srcProfile) return;
30
31
  // Select dstProfile and dstFormat
32
5.07k
  cmsHPROFILE dstProfile;
33
5.07k
  uint32_t dstFormat;
34
5.07k
  if (dstVal == 1) {
35
379
    dstProfile = cmsCreateLab4Profile(NULL);
36
379
    dstFormat = TYPE_Lab_8;
37
379
  }
38
4.69k
  else if (dstVal == 2) {
39
991
    dstProfile = cmsCreateLab2Profile(NULL);
40
991
    dstFormat = TYPE_LabV2_8;
41
991
  }
42
3.70k
  else if (dstVal == 3) {
43
231
    cmsToneCurve* gamma18;
44
231
    gamma18 = cmsBuildGamma(0, 1.8);
45
231
    dstProfile = cmsCreateGrayProfile(NULL, gamma18);
46
231
    cmsFreeToneCurve(gamma18);
47
231
    dstFormat = TYPE_GRAY_FLT | EXTRA_SH(1);
48
231
  }
49
3.47k
  else if (dstVal == 4) {
50
555
    dstProfile = cmsCreateXYZProfile();
51
555
    dstFormat = TYPE_XYZ_16;
52
555
  }
53
2.92k
  else if (dstVal == 5) {
54
361
    dstProfile = cmsCreateXYZProfile();
55
361
    dstFormat = TYPE_XYZ_DBL;
56
361
  }
57
2.56k
  else if (dstVal == 6) {
58
700
    dstProfile = cmsCreateLab4Profile(NULL);
59
700
    dstFormat = TYPE_Lab_DBL;
60
700
  }
61
1.86k
  else if (dstVal == 7) {
62
313
    dstProfile = cmsCreateLab4Profile(NULL);
63
313
    dstFormat = TYPE_Lab_DBL;
64
313
  }
65
1.54k
  else {
66
1.54k
    dstProfile = cmsCreate_sRGBProfile();
67
1.54k
    dstFormat = TYPE_RGB_8;
68
1.54k
  }
69
70
5.07k
  if (!dstProfile) {
71
0
    cmsCloseProfile(srcProfile);
72
0
    return;
73
0
  }
74
75
  // Extract srcFormat from the random src profile
76
5.07k
  cmsColorSpaceSignature srcCS = cmsGetColorSpace(srcProfile);
77
5.07k
  cmsUInt32Number nSrcComponents = cmsChannelsOf(srcCS);
78
5.07k
  cmsUInt32Number srcFormat;
79
5.07k
  if (srcCS == cmsSigLabData) {
80
267
    if (dstVal != 7) {
81
259
        srcFormat =
82
259
            COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0);
83
259
    }
84
8
    else {
85
8
        srcFormat =
86
8
            COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0) | FLOAT_SH(1);
87
8
    }
88
4.81k
  } else {
89
4.81k
    srcFormat =
90
4.81k
        COLORSPACE_SH(PT_ANY) | CHANNELS_SH(nSrcComponents) | BYTES_SH(1);
91
4.81k
  }
92
93
  // Create the transform
94
5.07k
  cmsContext ctx = cmsCreateContext(NULL, NULL);
95
5.07k
  cmsHTRANSFORM hTransform = cmsCreateTransformTHR(
96
5.07k
    ctx,
97
5.07k
    srcProfile,
98
5.07k
    srcFormat,
99
5.07k
    dstProfile,
100
5.07k
    dstFormat,
101
5.07k
    intent,
102
5.07k
    flags);
103
104
5.07k
  cmsCloseProfile(srcProfile);
105
5.07k
  cmsCloseProfile(dstProfile);
106
5.07k
  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
960
  if (T_BYTES(srcFormat) == 0) {  // 0 means double
113
    // Ensure output is large enough
114
4
    long long output[nSrcComponents*4];
115
4
    double input[nSrcComponents];
116
16
    for (uint32_t i = 0; i < nSrcComponents; i++) input[i] = 0.5f;
117
4
    cmsDoTransform(hTransform, input, output, 1);
118
4
  } 
119
956
  else {
120
956
    uint8_t input[nSrcComponents];
121
3.96k
    for (uint32_t i = 0; i < nSrcComponents; i++) input[i] = 128;
122
123
956
    if (dstFormat == TYPE_XYZ_16) {
124
88
      cmsCIEXYZ output_XYZ = { 0, 0, 0 };
125
88
      cmsDoTransform(hTransform, input, &output_XYZ, 1);
126
88
    }
127
868
    else if (dstFormat == TYPE_XYZ_DBL) {
128
41
      cmsCIEXYZTRIPLE out[4];
129
41
      cmsDoTransform(hTransform, input, out, 1);
130
41
    }
131
827
    else if (dstFormat == TYPE_Lab_DBL) {
132
104
      cmsCIELab Lab1;
133
104
      cmsDoTransform(hTransform, input, &Lab1, 1);
134
104
    }
135
723
    else {
136
723
      uint8_t output[4];
137
723
      cmsDoTransform(hTransform, input, output, 1);
138
723
    }
139
956
  }
140
960
  cmsDeleteTransform(hTransform);
141
960
}
142
143
144
13.3k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
145
13.3k
  if (size < 12) {
146
12
    return 0;
147
12
  }
148
149
13.3k
  uint32_t flags         = *((const uint32_t *)data+0);
150
13.3k
  uint32_t intent        = *((const uint32_t *)data+1) % 16;
151
13.3k
  int decider = *((int*)data+2) % 10;
152
13.3k
  data += 12;
153
13.3k
  size -= 12;
154
155
  // Transform using various output formats.
156
13.3k
  run_test(data, size, intent, flags, decider);
157
158
13.3k
  return 0;
159
13.3k
}