Coverage Report

Created: 2026-05-24 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tidy_general_fuzzer.c
Line
Count
Source
1
/*
2
 * Copyright 2021 Google LLC
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
#include <sys/types.h>
17
#include <stdlib.h>
18
#include <stdio.h>
19
#include <stdint.h>
20
#include <string.h>
21
#include <unistd.h>
22
#include "tidybuffio.h"
23
#include "tidy.h"
24
25
// All boolean options. These will be set randomly
26
// based on the fuzzer data.
27
TidyOptionId bool_options[] = {
28
  TidyJoinClasses, 
29
  TidyJoinStyles, 
30
  TidyKeepFileTimes, 
31
  TidyKeepTabs, 
32
  TidyLiteralAttribs, 
33
  TidyLogicalEmphasis, 
34
  TidyLowerLiterals, 
35
  TidyMakeBare, 
36
  TidyFixUri, 
37
  TidyForceOutput, 
38
  TidyGDocClean, 
39
  TidyHideComments,
40
  TidyMark, 
41
  TidyXmlTags, 
42
  TidyMakeClean,
43
  TidyAnchorAsName, 
44
  TidyMergeEmphasis,
45
  TidyMetaCharset,
46
  TidyMuteShow, 
47
  TidyNCR, 
48
  TidyNumEntities, 
49
  TidyOmitOptionalTags, 
50
  TidyPunctWrap, 
51
  TidyQuiet,
52
  TidyQuoteAmpersand,  
53
  TidyQuoteMarks, 
54
  TidyQuoteNbsp, 
55
  TidyReplaceColor, 
56
  TidyShowFilename, 
57
  TidyShowInfo, 
58
  TidyShowMarkup, 
59
  TidyShowMetaChange, 
60
  TidyShowWarnings, 
61
  TidySkipNested, 
62
  TidyUpperCaseTags, 
63
  TidyWarnPropAttrs, 
64
  TidyWord2000, 
65
  TidyWrapAsp, 
66
  TidyWrapAttVals, 
67
  TidyWrapJste, 
68
  TidyWrapPhp, 
69
  TidyWrapScriptlets, 
70
  TidyWrapSection, 
71
  TidyWriteBack,
72
};
73
74
77.1k
void set_option(const uint8_t** data, size_t *size, TidyDoc *tdoc, TidyOptionId tboolID) {
75
77.1k
  uint8_t decider;
76
77.1k
  decider = **data;
77
77.1k
  *data += 1; 
78
77.1k
  *size -= 1;
79
77.1k
  if (decider % 2 == 0) tidyOptSetBool( *tdoc, tboolID, yes );
80
33.1k
  else { tidyOptSetBool( *tdoc, tboolID, no ); }
81
77.1k
}
82
83
1.75k
int TidyXhtml(const uint8_t* data, size_t size, TidyBuffer* output, TidyBuffer* errbuf) {
84
1.75k
  uint8_t decider;
85
86
  // We need enough data for picking all of the options. One byte per option.
87
1.75k
  if (size < 5+(sizeof(bool_options)/sizeof(bool_options[0]))) {
88
0
    return 0;
89
0
  }
90
91
1.75k
  TidyDoc tdoc = tidyCreate();
92
1.75k
  if (!tdoc) {
93
0
    return 0;
94
0
  }
95
96
  // Decide output format
97
1.75k
  decider = *data;
98
1.75k
  data++; size--;
99
1.75k
  if (decider % 3 == 0) tidyOptSetBool( tdoc, TidyXhtmlOut, yes );
100
650
  else { tidyOptSetBool( tdoc, TidyXhtmlOut, no ); }
101
102
1.75k
  if (decider % 3 == 1) tidyOptSetBool( tdoc, TidyHtmlOut, yes );
103
1.33k
  else { tidyOptSetBool( tdoc, TidyHtmlOut, no ); }
104
105
1.75k
  if (decider % 3 == 2) tidyOptSetBool( tdoc, TidyXmlOut, yes );
106
1.52k
  else { tidyOptSetBool( tdoc, TidyXmlOut, no ); }
107
108
  // Set options 
109
78.9k
  for (int i=0; i < sizeof(bool_options)/sizeof(TidyOptionId); i++) {
110
77.1k
    set_option(&data, &size, &tdoc, bool_options[i]);
111
77.1k
  }
112
113
  // Set an error buffer.
114
1.75k
  tidySetErrorBuffer(tdoc, errbuf);
115
116
  // Parse the data
117
1.75k
  decider = *data;
118
1.75k
  data++; size--;
119
1.75k
  switch (decider % 2) {
120
1.46k
    case 0: {
121
1.46k
      char filename[256];
122
1.46k
      sprintf(filename, "/tmp/libfuzzer.%d", getpid());
123
124
1.46k
      FILE *fp = fopen(filename, "wb");
125
1.46k
      if (!fp) {
126
0
          tidyRelease(tdoc);
127
0
          return 0;
128
0
      }
129
1.46k
      fwrite(data, size, 1, fp);
130
1.46k
      fclose(fp);
131
132
1.46k
      tidyParseFile(tdoc, filename);
133
1.46k
      unlink(filename);
134
1.46k
    }
135
0
    break;
136
290
    case 1: {
137
290
      char *inp = malloc(size+1);
138
290
      inp[size] = '\0';
139
290
      memcpy(inp, data, size);
140
290
      tidyParseString(tdoc, inp);
141
290
      free(inp);
142
290
    }
143
1.75k
  }
144
145
  // Process and save output like other tidy fuzzers
146
1.75k
  tidyCleanAndRepair(tdoc);
147
1.75k
  tidyRunDiagnostics(tdoc);
148
1.75k
  tidyOptSetBool(tdoc, TidyForceOutput, yes);
149
1.75k
  tidySaveBuffer(tdoc, output);
150
151
  // Cleanup
152
1.75k
  tidyRelease( tdoc );
153
154
1.75k
  return 0;
155
1.75k
}
156
157
1.75k
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
158
1.75k
  TidyBuffer fuzz_toutput;
159
1.75k
  TidyBuffer fuzz_terror;
160
161
1.75k
  tidyBufInit(&fuzz_toutput);
162
1.75k
  tidyBufInit(&fuzz_terror);
163
164
1.75k
  TidyXhtml(data, size, &fuzz_toutput, &fuzz_terror);
165
166
1.75k
  tidyBufFree(&fuzz_toutput);
167
1.75k
  tidyBufFree(&fuzz_terror);
168
169
1.75k
  return 0;
170
1.75k
}