Coverage Report

Created: 2023-06-07 06:55

/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.70k
         uint32_t flags, int dstVal) {
24
5.70k
  if (size < 2) {
25
2
    return;
26
2
  }
27
28
5.70k
  cmsHPROFILE srcProfile = cmsOpenProfileFromMem(data, size);
29
5.70k
  if (!srcProfile) return;
30
31
  // Select dstProfile and dstFormat
32
5.01k
  cmsHPROFILE dstProfile;
33
5.01k
  uint32_t dstFormat;
34
5.01k
  if (dstVal == 1) {
35
469
    dstProfile = cmsCreateLab4Profile(NULL);
36
469
    dstFormat = TYPE_Lab_8;
37
469
  }
38
4.54k
  else if (dstVal == 2) {
39
1.10k
    dstProfile = cmsCreateLab2Profile(NULL);
40
1.10k
    dstFormat = TYPE_LabV2_8;
41
1.10k
  }
42
3.44k
  else if (dstVal == 3) {
43
225
    cmsToneCurve* gamma18;
44
225
    gamma18 = cmsBuildGamma(0, 1.8);
45
225
    dstProfile = cmsCreateGrayProfile(NULL, gamma18);
46
225
    cmsFreeToneCurve(gamma18);
47
225
    dstFormat = TYPE_GRAY_FLT | EXTRA_SH(1);
48
225
  }
49
3.21k
  else if (dstVal == 4) {
50
567
    dstProfile = cmsCreateXYZProfile();
51
567
    dstFormat = TYPE_XYZ_16;
52
567
  }
53
2.65k
  else if (dstVal == 5) {
54
385
    dstProfile = cmsCreateXYZProfile();
55
385
    dstFormat = TYPE_XYZ_DBL;
56
385
  }
57
2.26k
  else if (dstVal == 6) {
58
521
    dstProfile = cmsCreateLab4Profile(NULL);
59
521
    dstFormat = TYPE_Lab_DBL;
60
521
  }
61
1.74k
  else if (dstVal == 7) {
62
235
    dstProfile = cmsCreateLab4Profile(NULL);
63
235
    dstFormat = TYPE_Lab_DBL;
64
235
  }
65
1.51k
  else {
66
1.51k
    dstProfile = cmsCreate_sRGBProfile();
67
1.51k
    dstFormat = TYPE_RGB_8;
68
1.51k
  }
69
70
5.01k
  if (!dstProfile) {
71
0
    cmsCloseProfile(srcProfile);
72
0
    return;
73
0
  }
74
75
  // Extract srcFormat from the random src profile
76
5.01k
  cmsColorSpaceSignature srcCS = cmsGetColorSpace(srcProfile);
77
5.01k
  cmsUInt32Number nSrcComponents = cmsChannelsOf(srcCS);
78
5.01k
  cmsUInt32Number srcFormat;
79
5.01k
  if (srcCS == cmsSigLabData) {
80
298
    if (dstVal != 7) {
81
287
        srcFormat =
82
287
            COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0);
83
287
    }
84
11
    else {
85
11
        srcFormat =
86
11
            COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0) | FLOAT_SH(1);
87
11
    }
88
4.72k
  } else {
89
4.72k
    srcFormat =
90
4.72k
        COLORSPACE_SH(PT_ANY) | CHANNELS_SH(nSrcComponents) | BYTES_SH(1);
91
4.72k
  }
92
93
  // Create the transform
94
5.01k
  cmsContext ctx = cmsCreateContext(NULL, NULL);
95
5.01k
  cmsHTRANSFORM hTransform = cmsCreateTransformTHR(
96
5.01k
    ctx,
97
5.01k
    srcProfile,
98
5.01k
    srcFormat,
99
5.01k
    dstProfile,
100
5.01k
    dstFormat,
101
5.01k
    intent,
102
5.01k
    flags);
103
104
5.01k
  cmsCloseProfile(srcProfile);
105
5.01k
  cmsCloseProfile(dstProfile);
106
5.01k
  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
948
  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
940
  else {
120
940
    uint8_t input[nSrcComponents];
121
4.13k
    for (uint32_t i = 0; i < nSrcComponents; i++) input[i] = 128;
122
123
940
    if (dstFormat == TYPE_XYZ_16) {
124
70
      cmsCIEXYZ output_XYZ = { 0, 0, 0 };
125
70
      cmsDoTransform(hTransform, input, &output_XYZ, 1);
126
70
    }
127
870
    else if (dstFormat == TYPE_XYZ_DBL) {
128
39
      cmsCIEXYZTRIPLE out[4];
129
39
      cmsDoTransform(hTransform, input, out, 1);
130
39
    }
131
831
    else if (dstFormat == TYPE_Lab_DBL) {
132
86
      cmsCIELab Lab1;
133
86
      cmsDoTransform(hTransform, input, &Lab1, 1);
134
86
    }
135
745
    else {
136
745
      uint8_t output[4];
137
745
      cmsDoTransform(hTransform, input, output, 1);
138
745
    }
139
940
  }
140
948
  cmsDeleteTransform(hTransform);
141
948
}
142
143
144
13.8k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
145
13.8k
  if (size < 12) {
146
12
    return 0;
147
12
  }
148
149
13.8k
  uint32_t flags         = *((const uint32_t *)data+0);
150
13.8k
  uint32_t intent        = *((const uint32_t *)data+1) % 16;
151
13.8k
  int decider = *((int*)data+2) % 10;
152
13.8k
  data += 12;
153
13.8k
  size -= 12;
154
155
  // Transform using various output formats.
156
13.8k
  run_test(data, size, intent, flags, decider);
157
158
13.8k
  return 0;
159
13.8k
}