Skip to content

Commit 6e91cdf

Browse files
authored
Merge pull request #23 from pushinl/PR
fix fuzz_ppd_cache, del fuzz_ppd_options
2 parents 2ddc8f6 + f072478 commit 6e91cdf

File tree

5 files changed

+330
-89
lines changed

5 files changed

+330
-89
lines changed
Lines changed: 330 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,359 @@
11
#include <stdio.h>
22
#include <stdlib.h>
33
#include <string.h>
4+
#include <unistd.h>
5+
#include <stdint.h>
46
#include "ppd.h"
7+
#include "ppd-private.h"
58
#include "cups.h"
69
#include "ipp.h"
710
#include "file-private.h"
811

12+
// Global variables for cleanup
13+
static char *g_ppd_file = NULL;
14+
static char *g_cache_file = NULL;
15+
16+
// Cleanup function
17+
static void cleanup_files(void)
18+
{
19+
if (g_ppd_file)
20+
{
21+
unlink(g_ppd_file);
22+
free(g_ppd_file);
23+
g_ppd_file = NULL;
24+
}
25+
if (g_cache_file)
26+
{
27+
unlink(g_cache_file);
28+
free(g_cache_file);
29+
g_cache_file = NULL;
30+
}
31+
}
32+
33+
// Parse input data into segments
34+
static int parse_input_segments(const uint8_t *data, size_t size,
35+
const uint8_t **segments, size_t *seg_sizes, int max_segments)
36+
{
37+
if (size < 4)
38+
return 0;
39+
40+
uint32_t num_segments = *(uint32_t *)data;
41+
if (num_segments == 0 || num_segments > max_segments)
42+
return 0;
43+
44+
const uint8_t *ptr = data + 4;
45+
size_t remaining = size - 4;
46+
47+
for (uint32_t i = 0; i < num_segments && i < max_segments; i++)
48+
{
49+
if (remaining < 4)
50+
return i;
51+
52+
uint32_t seg_len = *(uint32_t *)ptr;
53+
ptr += 4;
54+
remaining -= 4;
55+
56+
if (seg_len > remaining)
57+
return i;
58+
59+
segments[i] = ptr;
60+
seg_sizes[i] = seg_len;
61+
ptr += seg_len;
62+
remaining -= seg_len;
63+
}
64+
65+
return num_segments;
66+
}
67+
68+
// Create a simple IPP job for testing
69+
static ipp_t *create_test_job(const uint8_t *data, size_t size)
70+
{
71+
ipp_t *job = ippNew();
72+
if (!job)
73+
return NULL;
74+
75+
// Add some basic attributes using fuzz data
76+
if (size > 10)
77+
{
78+
char media_name[64];
79+
snprintf(media_name, sizeof(media_name), "media-%02x%02x", data[0], data[1]);
80+
ippAddString(job, IPP_TAG_JOB, IPP_TAG_KEYWORD, "media", NULL, media_name);
81+
}
82+
83+
if (size > 20)
84+
{
85+
char source_name[64];
86+
snprintf(source_name, sizeof(source_name), "source-%02x%02x", data[10], data[11]);
87+
ippAddString(job, IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-source", NULL, source_name);
88+
}
89+
90+
if (size > 30)
91+
{
92+
char type_name[64];
93+
snprintf(type_name, sizeof(type_name), "type-%02x%02x", data[20], data[21]);
94+
ippAddString(job, IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, type_name);
95+
}
96+
97+
return job;
98+
}
99+
100+
// Test all cache GET functions
101+
static void test_cache_functions(_ppd_cache_t *pc, ppd_file_t *ppd, const uint8_t **segments, size_t *seg_sizes, int num_segments)
102+
{
103+
if (!pc)
104+
return;
105+
106+
// Test _ppdCacheGetBin
107+
if (num_segments > 4 && seg_sizes[4] > 0)
108+
{
109+
char bin_name[256];
110+
size_t copy_len = seg_sizes[4] < sizeof(bin_name) - 1 ? seg_sizes[4] : sizeof(bin_name) - 1;
111+
memcpy(bin_name, segments[4], copy_len);
112+
bin_name[copy_len] = '\0';
113+
114+
const char *result = _ppdCacheGetBin(pc, bin_name);
115+
(void)result; // Suppress unused variable warning
116+
}
117+
118+
// Test _ppdCacheGetOutputBin
119+
if (num_segments > 4 && seg_sizes[4] > 0)
120+
{
121+
char output_bin[256];
122+
size_t copy_len = seg_sizes[4] < sizeof(output_bin) - 1 ? seg_sizes[4] : sizeof(output_bin) - 1;
123+
memcpy(output_bin, segments[4], copy_len);
124+
output_bin[copy_len] = '\0';
125+
126+
const char *result = _ppdCacheGetOutputBin(pc, output_bin);
127+
(void)result;
128+
}
129+
130+
// Test _ppdCacheGetSource
131+
if (num_segments > 3 && seg_sizes[3] > 0)
132+
{
133+
char input_slot[256];
134+
size_t copy_len = seg_sizes[3] < sizeof(input_slot) - 1 ? seg_sizes[3] : sizeof(input_slot) - 1;
135+
memcpy(input_slot, segments[3], copy_len);
136+
input_slot[copy_len] = '\0';
137+
138+
const char *result = _ppdCacheGetSource(pc, input_slot);
139+
(void)result;
140+
}
141+
142+
// Test _ppdCacheGetType
143+
if (num_segments > 2 && seg_sizes[2] > 0)
144+
{
145+
char media_type[256];
146+
size_t copy_len = seg_sizes[2] < sizeof(media_type) - 1 ? seg_sizes[2] : sizeof(media_type) - 1;
147+
memcpy(media_type, segments[2], copy_len);
148+
media_type[copy_len] = '\0';
149+
150+
const char *result = _ppdCacheGetType(pc, media_type);
151+
(void)result;
152+
}
153+
154+
// Test _ppdCacheGetPageSize with keyword
155+
if (num_segments > 1 && seg_sizes[1] > 0)
156+
{
157+
char page_size[256];
158+
size_t copy_len = seg_sizes[1] < sizeof(page_size) - 1 ? seg_sizes[1] : sizeof(page_size) - 1;
159+
memcpy(page_size, segments[1], copy_len);
160+
page_size[copy_len] = '\0';
161+
162+
int exact = 0;
163+
const char *result = _ppdCacheGetPageSize(pc, NULL, page_size, &exact);
164+
(void)result;
165+
}
166+
167+
// Test _ppdCacheGetPageSize with IPP job
168+
if (num_segments > 5 && seg_sizes[5] > 0)
169+
{
170+
ipp_t *job = create_test_job(segments[5], seg_sizes[5]);
171+
if (job)
172+
{
173+
int exact = 0;
174+
const char *result = _ppdCacheGetPageSize(pc, job, NULL, &exact);
175+
(void)result;
176+
ippDelete(job);
177+
}
178+
}
179+
180+
// Test _ppdCacheGetInputSlot
181+
if (num_segments > 5 && seg_sizes[5] > 0)
182+
{
183+
ipp_t *job = create_test_job(segments[5], seg_sizes[5]);
184+
if (job)
185+
{
186+
const char *result = _ppdCacheGetInputSlot(pc, job, NULL);
187+
(void)result;
188+
ippDelete(job);
189+
}
190+
}
191+
192+
// Test _ppdCacheGetMediaType
193+
if (num_segments > 5 && seg_sizes[5] > 0)
194+
{
195+
ipp_t *job = create_test_job(segments[5], seg_sizes[5]);
196+
if (job)
197+
{
198+
const char *result = _ppdCacheGetMediaType(pc, job, NULL);
199+
(void)result;
200+
ippDelete(job);
201+
}
202+
}
203+
204+
// Test _ppdCacheGetSize
205+
if (num_segments > 1 && seg_sizes[1] > 0)
206+
{
207+
char page_size[256];
208+
size_t copy_len = seg_sizes[1] < sizeof(page_size) - 1 ? seg_sizes[1] : sizeof(page_size) - 1;
209+
memcpy(page_size, segments[1], copy_len);
210+
page_size[copy_len] = '\0';
211+
212+
pwg_size_t *result = _ppdCacheGetSize(pc, page_size, NULL);
213+
(void)result;
214+
}
215+
216+
// Test _ppdCacheGetFinishingValues
217+
if (ppd)
218+
{
219+
int finishings[20];
220+
int num_finishings = _ppdCacheGetFinishingValues(ppd, pc, 20, finishings);
221+
(void)num_finishings;
222+
}
223+
224+
// Test _ppdCacheGetFinishingOptions
225+
if (num_segments > 5 && seg_sizes[5] > 0)
226+
{
227+
ipp_t *job = create_test_job(segments[5], seg_sizes[5]);
228+
if (job)
229+
{
230+
cups_option_t *options = NULL;
231+
int num_options = 0;
232+
num_options = _ppdCacheGetFinishingOptions(pc, job, IPP_FINISHINGS_NONE, num_options, &options);
233+
234+
if (options)
235+
{
236+
cupsFreeOptions(num_options, options);
237+
}
238+
ippDelete(job);
239+
}
240+
}
241+
}
242+
9243
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
10244
{
11-
// Create a temporary file to simulate a PPD file
12-
char filename[256];
13-
snprintf(filename, sizeof(filename), "/tmp/fuzz_ppd_%d.ppd", getpid());
14-
FILE *file = fopen(filename, "wb");
245+
// Minimum size check
246+
if (size < 100)
247+
{
248+
return 0;
249+
}
250+
251+
// Setup cleanup
252+
atexit(cleanup_files);
253+
254+
// Create filenames with cursor_test_ prefix
255+
g_ppd_file = malloc(256);
256+
g_cache_file = malloc(256);
257+
if (!g_ppd_file || !g_cache_file)
258+
{
259+
cleanup_files();
260+
return 0;
261+
}
262+
263+
snprintf(g_ppd_file, 256, "/tmp/cursor_test_ppd_%d.ppd", getpid());
264+
snprintf(g_cache_file, 256, "/tmp/cursor_test_cache_%d.cache", getpid());
265+
266+
// Parse input segments
267+
const uint8_t *segments[10];
268+
size_t seg_sizes[10];
269+
int num_segments = parse_input_segments(data, size, segments, seg_sizes, 10);
270+
271+
if (num_segments < 1)
272+
{
273+
cleanup_files();
274+
return 0;
275+
}
276+
277+
// Write PPD file data
278+
FILE *file = fopen(g_ppd_file, "wb");
15279
if (!file)
280+
{
281+
cleanup_files();
16282
return 0;
17-
fwrite(data, 1, size, file);
283+
}
284+
285+
fwrite(segments[0], 1, seg_sizes[0], file);
18286
fclose(file);
19287

20-
// Open the PPD file
21-
ppd_file_t *ppd = ppdOpenFile(filename);
288+
// Open PPD file
289+
ppd_file_t *ppd = ppdOpenFile(g_ppd_file);
22290
if (!ppd)
23291
{
24-
remove(filename);
292+
cleanup_files();
25293
return 0;
26294
}
27295

28-
// Create a cache with the PPD
29-
ipp_t *attrs = ippNew(); // Create a new IPP attributes object
30-
_ppd_cache_t *cache = _ppdCacheCreateWithPPD(attrs, ppd);
31-
if (cache)
296+
// Create cache from PPD
297+
_ppd_cache_t *cache = _ppdCacheCreateWithPPD(NULL, ppd);
298+
if (!cache)
32299
{
33-
// Optionally write the cache to a file
34-
char cache_filename[256];
35-
snprintf(cache_filename, sizeof(cache_filename), "/tmp/fuzz_cache_%d.cache", getpid());
36-
_ppdCacheWriteFile(cache, cache_filename, attrs);
37-
38-
// Retrieve data from the cache
39-
_ppdCacheGetBin(cache, "output-bin");
40-
int exact;
41-
_ppdCacheGetPageSize(cache, attrs, "page-size", &exact);
300+
ppdClose(ppd);
301+
cleanup_files();
302+
return 0;
303+
}
42304

43-
// Destroy the cache
44-
_ppdCacheDestroy(cache);
305+
// Test all cache functions
306+
test_cache_functions(cache, ppd, segments, seg_sizes, num_segments);
45307

46-
// Clean up the cache file
47-
remove(cache_filename);
308+
// Test cache file write/read cycle
309+
if (_ppdCacheWriteFile(cache, g_cache_file, NULL))
310+
{
311+
ipp_t *attrs = NULL;
312+
_ppd_cache_t *cache2 = _ppdCacheCreateWithFile(g_cache_file, &attrs);
313+
if (cache2)
314+
{
315+
// Test functions on loaded cache
316+
test_cache_functions(cache2, ppd, segments, seg_sizes, num_segments);
317+
_ppdCacheDestroy(cache2);
318+
}
319+
if (attrs)
320+
{
321+
ippDelete(attrs);
322+
}
48323
}
49324

50-
// Clean up IPP attributes
51-
ippDelete(attrs);
325+
// Test _cupsConvertOptions if we have enough segments
326+
if (num_segments > 6 && seg_sizes[6] > 0)
327+
{
328+
ipp_t *request = ippNewRequest(IPP_OP_PRINT_JOB);
329+
if (request)
330+
{
331+
cups_option_t *options = NULL;
332+
int num_options = 0;
52333

53-
// Close the PPD file
54-
ppdClose(ppd);
334+
// Parse options from segment data
335+
char options_str[1024];
336+
size_t copy_len = seg_sizes[6] < sizeof(options_str) - 1 ? seg_sizes[6] : sizeof(options_str) - 1;
337+
memcpy(options_str, segments[6], copy_len);
338+
options_str[copy_len] = '\0';
339+
340+
num_options = cupsParseOptions(options_str, num_options, &options);
341+
342+
if (num_options > 0)
343+
{
344+
_cupsConvertOptions(request, ppd, cache, NULL, NULL, NULL,
345+
"testuser", "application/pdf", 1, num_options, options);
346+
cupsFreeOptions(num_options, options);
347+
}
55348

56-
// Remove the temporary PPD file
57-
remove(filename);
349+
ippDelete(request);
350+
}
351+
}
352+
353+
// Cleanup resources
354+
_ppdCacheDestroy(cache);
355+
ppdClose(ppd);
356+
cleanup_files();
58357

59358
return 0;
60359
}

0 commit comments

Comments
 (0)