Coverage Report

Created: 2026-02-14 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cms_transform_extended_fuzzer.c
Line
Count
Source
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.94k
         uint32_t flags, int dstVal) {
24
5.94k
  if (size < 2) {
25
2
    return;
26
2
  }
27
28
5.94k
  cmsHPROFILE srcProfile = cmsOpenProfileFromMem(data, size);
29
5.94k
  if (!srcProfile) return;
30
31
  // Select dstProfile and dstFormat
32
5.25k
  cmsHPROFILE dstProfile;
33
5.25k
  uint32_t dstFormat;
34
5.25k
  if (dstVal == 1) {
35
487
    dstProfile = cmsCreateLab4Profile(NULL);
36
487
    dstFormat = TYPE_Lab_8;
37
487
  }
38
4.77k
  else if (dstVal == 2) {
39
487
    dstProfile = cmsCreateLab2Profile(NULL);
40
487
    dstFormat = TYPE_LabV2_8;
41
487
  }
42
4.28k
  else if (dstVal == 3) {
43
179
    cmsToneCurve* gamma18;
44
179
    gamma18 = cmsBuildGamma(0, 1.8);
45
179
    dstProfile = cmsCreateGrayProfile(NULL, gamma18);
46
179
    cmsFreeToneCurve(gamma18);
47
179
    dstFormat = TYPE_GRAY_FLT | EXTRA_SH(1);
48
179
  }
49
4.10k
  else if (dstVal == 4) {
50
561
    dstProfile = cmsCreateXYZProfile();
51
561
    dstFormat = TYPE_XYZ_16;
52
561
  }
53
3.54k
  else if (dstVal == 5) {
54
317
    dstProfile = cmsCreateXYZProfile();
55
317
    dstFormat = TYPE_XYZ_DBL;
56
317
  }
57
3.22k
  else if (dstVal == 6) {
58
535
    dstProfile = cmsCreateLab4Profile(NULL);
59
535
    dstFormat = TYPE_Lab_DBL;
60
535
  }
61
2.69k
  else if (dstVal == 7) {
62
354
    dstProfile = cmsCreateLab4Profile(NULL);
63
354
    dstFormat = TYPE_Lab_DBL;
64
354
  }
65
2.33k
  else if (dstVal == 8){
66
244
    dstProfile = cmsCreate_OkLabProfile(NULL);
67
244
    dstFormat = (FLOAT_SH(1)|COLORSPACE_SH(PT_MCH3)|CHANNELS_SH(3)|BYTES_SH(0));
68
244
  }
69
2.09k
  else if (dstVal == 9){
70
311
    dstProfile = cmsCreateNULLProfile();
71
311
    dstFormat = 0;
72
311
  }
73
1.78k
  else if (dstVal == 10){
74
484
    dstProfile = cmsCreateBCHSWabstractProfile(17, 0, 1.2, 0, 3, 5000, 5000);
75
484
    dstFormat = TYPE_Lab_DBL;
76
484
  }
77
1.30k
  else {
78
1.30k
    dstProfile = cmsCreate_sRGBProfile();
79
1.30k
    dstFormat = TYPE_RGB_8;
80
1.30k
  }
81
82
5.25k
  if (!dstProfile) {
83
0
    cmsCloseProfile(srcProfile);
84
0
    return;
85
0
  }
86
87
  // Extract srcFormat from the random src profile
88
5.25k
  cmsColorSpaceSignature srcCS = cmsGetColorSpace(srcProfile);
89
5.25k
  cmsUInt32Number nSrcComponents = cmsChannelsOf(srcCS);
90
5.25k
  cmsUInt32Number srcFormat;
91
5.25k
  if (srcCS == cmsSigLabData) {
92
354
    if (dstVal != 7) {
93
340
        srcFormat =
94
340
            COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0);
95
340
    }
96
14
    else {
97
14
        srcFormat =
98
14
            COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0) | FLOAT_SH(1);
99
14
    }
100
4.90k
  } else {
101
4.90k
    srcFormat =
102
4.90k
        COLORSPACE_SH(PT_ANY) | CHANNELS_SH(nSrcComponents) | BYTES_SH(1);
103
4.90k
  }
104
105
  // Create the transform
106
5.25k
  cmsContext ctx = cmsCreateContext(NULL, NULL);
107
5.25k
  cmsHTRANSFORM hTransform = cmsCreateTransformTHR(
108
5.25k
    ctx,
109
5.25k
    srcProfile,
110
5.25k
    srcFormat,
111
5.25k
    dstProfile,
112
5.25k
    dstFormat,
113
5.25k
    intent,
114
5.25k
    flags);
115
116
5.25k
  cmsCloseProfile(srcProfile);
117
5.25k
  cmsCloseProfile(dstProfile);
118
5.25k
  if (!hTransform) return;
119
120
121
  // Do transformation.
122
  // The output buffer type depends on the dstFormat
123
  // The input buffer type depends on the srcFormat.
124
1.13k
  if (T_BYTES(srcFormat) == 0) {  // 0 means double
125
    // Ensure output is large enough
126
4
    long long output[nSrcComponents*4];
127
4
    double input[nSrcComponents];
128
16
    for (uint32_t i = 0; i < nSrcComponents; i++) input[i] = 0.5f;
129
4
    cmsDoTransform(hTransform, input, output, 1);
130
4
  } 
131
1.12k
  else {
132
1.12k
    uint8_t input[nSrcComponents];
133
4.76k
    for (uint32_t i = 0; i < nSrcComponents; i++) input[i] = 128;
134
135
1.12k
    if (dstFormat == TYPE_XYZ_16) {
136
76
      cmsCIEXYZ output_XYZ = { 0, 0, 0 };
137
76
      cmsDoTransform(hTransform, input, &output_XYZ, 1);
138
76
    }
139
1.05k
    else if (dstFormat == TYPE_XYZ_DBL) {
140
45
      cmsCIEXYZTRIPLE out[4];
141
45
      cmsDoTransform(hTransform, input, out, 1);
142
45
    }
143
1.00k
    else if (dstFormat == TYPE_Lab_DBL || dstFormat == (FLOAT_SH(1)|COLORSPACE_SH(PT_MCH3)|CHANNELS_SH(3)|BYTES_SH(0))) {
144
326
      cmsCIELab Lab1;
145
326
      cmsDoTransform(hTransform, input, &Lab1, 1);
146
326
    }
147
679
    else {
148
679
      uint8_t output[4];
149
679
      cmsDoTransform(hTransform, input, output, 1);
150
679
    }
151
1.12k
  }
152
1.13k
  cmsDeleteTransform(hTransform);
153
1.13k
}
154
155
156
12.8k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
157
12.8k
  if (size < 12) {
158
12
    return 0;
159
12
  }
160
161
12.8k
  uint32_t flags         = *((const uint32_t *)data+0);
162
12.8k
  uint32_t intent        = *((const uint32_t *)data+1) % 16;
163
12.8k
  int decider = *((int*)data+2) % 11;
164
12.8k
  data += 12;
165
12.8k
  size -= 12;
166
167
  // Transform using various output formats.
168
12.8k
  run_test(data, size, intent, flags, decider);
169
170
12.8k
  return 0;
171
12.8k
}