Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gs_pcl_fuzzer.cc
Line
Count
Source
1
/* Copyright 2026 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
/*
14
 * Fuzzer for Ghostscript's PCL5 interpreter.
15
 *
16
 * PCL5 is a binary escape-sequence format used in printers. The ghostpdl
17
 * auto-detection recognizes PCL by ESC (0x1b) bytes in the input. We write
18
 * fuzz data to a temp file and pass it as a filename so that ghostpdl can
19
 * use seekable I/O and proper language auto-detection.
20
 *
21
 * We prepend ESC-E (PCL reset) to ensure the auto-detector routes the
22
 * input to the PCL interpreter (confidence 100 in pcl_detect_language).
23
 */
24
25
#include <base/gserrors.h>
26
#include <psi/iapi.h>
27
28
#include <stdint.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <unistd.h>
33
34
static int gs_stdnull(void *inst, const char *buf, int len)
35
12
{
36
12
  return len;
37
12
}
38
39
6.05k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
40
6.05k
  if (size == 0)
41
0
    return 0;
42
43
  /* Write fuzz data to temp file with ESC-E prefix */
44
6.05k
  char infile[256];
45
6.05k
  sprintf(infile, "/tmp/fuzz_pcl.%d", getpid());
46
6.05k
  FILE *f = fopen(infile, "wb");
47
6.05k
  if (!f)
48
0
    return 0;
49
  /* PCL reset: ensures pcl_detect_language returns 100 */
50
6.05k
  fputc(0x1b, f);
51
6.05k
  fputc('E', f);
52
6.05k
  fwrite(data, 1, size, f);
53
6.05k
  fclose(f);
54
55
6.05k
  void *gs = NULL;
56
6.05k
  int ret = gsapi_new_instance(&gs, NULL);
57
6.05k
  if (ret < 0) {
58
0
    unlink(infile);
59
0
    return 0;
60
0
  }
61
62
6.05k
  gsapi_set_stdio(gs, NULL, gs_stdnull, gs_stdnull);
63
6.05k
  gsapi_set_arg_encoding(gs, GS_ARG_ENCODING_UTF8);
64
65
6.05k
  char *args[] = {
66
6.05k
    (char *)"gpdl",
67
6.05k
    (char *)"-dNOPAUSE",
68
6.05k
    (char *)"-dBATCH",
69
6.05k
    (char *)"-dQUIET",
70
6.05k
    (char *)"-dSAFER",
71
6.05k
    (char *)"-sDEVICE=nullpage",
72
6.05k
    (char *)"-sOutputFile=/dev/null",
73
6.05k
    (char *)"-r72x72",
74
6.05k
    infile,
75
6.05k
  };
76
6.05k
  int argc = sizeof(args) / sizeof(args[0]);
77
78
6.05k
  ret = gsapi_init_with_args(gs, argc, args);
79
6.05k
  gsapi_exit(gs);
80
6.05k
  gsapi_delete_instance(gs);
81
82
6.05k
  unlink(infile);
83
6.05k
  return 0;
84
6.05k
}