Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | # Copyright 2019 The Chromium OS Authors. |
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 | | ################################################################################ |
17 | | */ |
18 | | |
19 | | #include <base/gserrors.h> |
20 | | #include <psi/iapi.h> |
21 | | |
22 | | #include <limits.h> |
23 | | #include <stdio.h> |
24 | | #include <string.h> |
25 | | #include <stdint.h> |
26 | | |
27 | | static const unsigned char *g_data; |
28 | | static size_t g_size; |
29 | | |
30 | | int fuzz_gs_device( |
31 | | const unsigned char *buf, |
32 | | size_t size, |
33 | | int color_scheme, |
34 | | const char *device_target, |
35 | | const char *output_file, |
36 | | int do_interpolation |
37 | | ); |
38 | | |
39 | 149k | #define min(x, y) ((x) < (y) ? (x) : (y)) |
40 | | |
41 | | static int gs_stdin(void *inst, char *buf, int len) |
42 | 74.6k | { |
43 | 74.6k | size_t to_copy = min(len, g_size); |
44 | 74.6k | to_copy = min(INT_MAX, to_copy); |
45 | | |
46 | 74.6k | memcpy(buf, g_data, to_copy); |
47 | | |
48 | 74.6k | g_data += to_copy; |
49 | 74.6k | g_size -= to_copy; |
50 | | |
51 | 74.6k | return to_copy; |
52 | 74.6k | } |
53 | | |
54 | | static int gs_stdnull(void *inst, const char *buf, int len) |
55 | 19.3k | { |
56 | | /* Just discard everything. */ |
57 | 19.3k | return len; |
58 | 19.3k | } |
59 | | |
60 | | int gs_to_raster_fuzz( |
61 | | const unsigned char *buf, |
62 | | size_t size, |
63 | | int color_scheme |
64 | | ) |
65 | 0 | { |
66 | 0 | return fuzz_gs_device(buf, size, color_scheme, "cups", "/dev/null", 0); |
67 | 0 | } |
68 | | |
69 | | int fuzz_gs_device( |
70 | | const unsigned char *buf, |
71 | | size_t size, |
72 | | int color_scheme, |
73 | | const char *device_target, |
74 | | const char *output_file, |
75 | | int do_interpolation |
76 | | ) |
77 | 9.57k | { |
78 | 9.57k | int ret; |
79 | 9.57k | void *gs = NULL; |
80 | 9.57k | char color_space[50]; |
81 | 9.57k | char gs_device[50]; |
82 | 9.57k | char gs_o[100]; |
83 | 9.57k | char opt_interpolation[50]; |
84 | | /* |
85 | | * We are expecting color_scheme to be in the [0:62] interval. |
86 | | * This corresponds to the color schemes defined here: |
87 | | * https://github.com/ArtifexSoftware/ghostpdl/blob/8c97d5adce0040ac38a1fb4d7954499c65f582ff/cups/libs/cups/raster.h#L102 |
88 | | */ |
89 | 9.57k | sprintf(color_space, "-dcupsColorSpace=%d", color_scheme); |
90 | 9.57k | sprintf(gs_device, "-sDEVICE=%s", device_target); |
91 | 9.57k | sprintf(gs_o, "-sOutputFile=%s", output_file); |
92 | 9.57k | if (do_interpolation) { |
93 | 0 | sprintf(opt_interpolation, "-dDOINTERPOLATE"); |
94 | 0 | } |
95 | 9.57k | else { |
96 | 9.57k | sprintf(opt_interpolation, "-dNOINTERPOLATE"); |
97 | 9.57k | } |
98 | | /* Mostly stolen from cups-filters gstoraster. */ |
99 | 9.57k | char *args[] = { |
100 | 9.57k | "gs", |
101 | 9.57k | "-K1048576", |
102 | 9.57k | "-r200x200", |
103 | 9.57k | "-sBandListStorage=memory", |
104 | 9.57k | "-dMaxBitmap=0", |
105 | 9.57k | "-dBufferSpace=450k", |
106 | 9.57k | "-dMediaPosition=1", |
107 | 9.57k | color_space, |
108 | 9.57k | "-dQUIET", |
109 | 9.57k | "-dSAFER", |
110 | 9.57k | "-dNOPAUSE", |
111 | 9.57k | "-dBATCH", |
112 | 9.57k | opt_interpolation, |
113 | 9.57k | "-dNOMEDIAATTRS", |
114 | 9.57k | "-sstdout=%%stderr", |
115 | 9.57k | gs_o, |
116 | 9.57k | gs_device, |
117 | 9.57k | "-_", |
118 | 9.57k | }; |
119 | 9.57k | int argc = sizeof(args) / sizeof(args[0]); |
120 | | |
121 | | /* Stash buffers globally, for gs_stdin(). */ |
122 | 9.57k | g_data = buf; |
123 | 9.57k | g_size = size; |
124 | | |
125 | 9.57k | ret = gsapi_new_instance(&gs, NULL); |
126 | 9.57k | if (ret < 0) { |
127 | 0 | fprintf(stderr, "gsapi_new_instance: error %d\n", ret); |
128 | 0 | return ret; |
129 | 0 | } |
130 | | |
131 | 9.57k | gsapi_set_stdio(gs, gs_stdin, gs_stdnull, gs_stdnull); |
132 | 9.57k | ret = gsapi_set_arg_encoding(gs, GS_ARG_ENCODING_UTF8); |
133 | 9.57k | if (ret < 0) { |
134 | 0 | fprintf(stderr, "gsapi_set_arg_encoding: error %d\n", ret); |
135 | 0 | gsapi_delete_instance(gs); |
136 | 0 | return ret; |
137 | 0 | } |
138 | | |
139 | 9.57k | ret = gsapi_init_with_args(gs, argc, args); |
140 | 9.57k | if (ret && ret != gs_error_Quit) |
141 | | /* Just keep going, to cleanup. */ |
142 | 2.94k | fprintf(stderr, "gsapi_init_with_args: error %d\n", ret); |
143 | | |
144 | 9.57k | ret = gsapi_exit(gs); |
145 | 9.57k | if (ret < 0 && ret != gs_error_Quit) { |
146 | 0 | fprintf(stderr, "gsapi_exit: error %d\n", ret); |
147 | 0 | return ret; |
148 | 0 | } |
149 | | |
150 | 9.57k | gsapi_delete_instance(gs); |
151 | | |
152 | 9.57k | return 0; |
153 | 9.57k | } |