Coverage Report

Created: 2025-11-16 06:37

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 <unistd.h>
21
#include "tidybuffio.h"
22
#include "tidy.h"
23
24
// All boolean options. These will be set randomly
25
// based on the fuzzer data.
26
TidyOptionId bool_options[] = {
27
  TidyJoinClasses, 
28
  TidyJoinStyles, 
29
  TidyKeepFileTimes, 
30
  TidyKeepTabs, 
31
  TidyLiteralAttribs, 
32
  TidyLogicalEmphasis, 
33
  TidyLowerLiterals, 
34
  TidyMakeBare, 
35
  TidyFixUri, 
36
  TidyForceOutput, 
37
  TidyGDocClean, 
38
  TidyHideComments,
39
  TidyMark, 
40
  TidyXmlTags, 
41
  TidyMakeClean,
42
  TidyAnchorAsName, 
43
  TidyMergeEmphasis, 
44
  TidyMakeBare, 
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
27.0k
void set_option(const uint8_t** data, size_t *size, TidyDoc *tdoc, TidyOptionId tboolID) {
75
27.0k
  uint8_t decider;
76
27.0k
  decider = **data;
77
27.0k
  *data += 1; 
78
27.0k
  *size -= 1;
79
27.0k
  if (decider % 2 == 0) tidyOptSetBool( *tdoc, tboolID, yes );
80
12.0k
  else { tidyOptSetBool( *tdoc, tboolID, no ); }
81
27.0k
}
82
83
600
int TidyXhtml(const uint8_t* data, size_t size, TidyBuffer* output, TidyBuffer* errbuf) {
84
600
  uint8_t decider;
85
86
  // We need enough data for picking all of the options. One byte per option.
87
600
  if (size < 5+(sizeof(bool_options)/sizeof(bool_options[0]))) {
88
0
    return 0;
89
0
  }
90
91
600
  TidyDoc tdoc = tidyCreate();
92
93
  // Decide output format
94
600
  decider = *data;
95
600
  data++; size--;
96
600
  if (decider % 3 == 0) tidyOptSetBool( tdoc, TidyXhtmlOut, yes );
97
248
  else { tidyOptSetBool( tdoc, TidyXhtmlOut, no ); }
98
99
600
  if (decider % 3 == 1) tidyOptSetBool( tdoc, TidyHtmlOut, yes );
100
448
  else { tidyOptSetBool( tdoc, TidyHtmlOut, no ); }
101
102
600
  if (decider % 3 == 2) tidyOptSetBool( tdoc, TidyXmlOut, yes );
103
504
  else { tidyOptSetBool( tdoc, TidyXmlOut, no ); }
104
105
  // Set options 
106
27.6k
  for (int i=0; i < sizeof(bool_options)/sizeof(TidyOptionId); i++) {
107
27.0k
    set_option(&data, &size, &tdoc, bool_options[i]);
108
27.0k
  }
109
110
  // Set an error buffer.
111
600
  tidySetErrorBuffer(tdoc, errbuf);
112
113
  // Parse the data
114
600
  decider = *data;
115
600
  data++; size--;
116
600
  switch (decider % 2) {
117
534
    case 0: {
118
534
      char filename[256];
119
534
      sprintf(filename, "/tmp/libfuzzer.%d", getpid());
120
121
534
      FILE *fp = fopen(filename, "wb");
122
534
      if (!fp) {
123
0
          return 0;
124
0
      }
125
534
      fwrite(data, size, 1, fp);
126
534
      fclose(fp);
127
128
534
      tidyParseFile(tdoc, filename);
129
534
      unlink(filename);
130
534
    }
131
0
    break;
132
66
    case 1: {
133
66
      char *inp = malloc(size+1);
134
66
      inp[size] = '\0';
135
66
      memcpy(inp, data, size);
136
66
      tidyParseString(tdoc, inp);
137
66
      free(inp);
138
66
    }
139
600
  }
140
141
  // Cleanup
142
600
  tidyRelease( tdoc );
143
144
600
  return 0;
145
600
}
146
147
600
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
148
600
  TidyBuffer fuzz_toutput;
149
600
  TidyBuffer fuzz_terror;
150
151
600
  tidyBufInit(&fuzz_toutput);
152
600
  tidyBufInit(&fuzz_terror);
153
154
600
  TidyXhtml(data, size, &fuzz_toutput, &fuzz_terror);
155
156
600
  tidyBufFree(&fuzz_toutput);
157
600
  tidyBufFree(&fuzz_terror);
158
159
600
  return 0;
160
600
}