Coverage Report

Created: 2023-04-12 06:16

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