blob: af7df01a342188f89a6c3dbbd0848802f8712103 [file]
// Copyright 2025 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/param.h>
#include <unistd.h>
#include "stdin_util.h"
#include "wrapper.h"
#include <cups/ppd.h>
#include <cups/raster.h>
// This PPD file is a randomly selected PPD file that uses the
// epson-escpr-wrapper filter.
const char ppdFile[] = "/usr/share/cups/model/epson.ppd";
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
static cups_page_header2_t header;
static bool once = true;
if (once) {
ppd_file_t *file = ppdOpenFile(ppdFile);
if (!file) {
fprintf(stderr, "ppdOpenFile() failed\n");
abort();
}
if (cupsRasterInterpretPPD(&header, file, 0, NULL, NULL) < 0) {
fprintf(stderr, "cupsRasterInterpretPPD() failed\n");
ppdClose(file);
abort();
}
ppdClose(file);
header.HWResolution[0] = 360;
header.HWResolution[1] = 360;
once = false;
}
if (setenv("PPD", ppdFile, true)) {
fprintf(stderr, "setenv failed: %s\n", strerror(errno));
abort();
}
// Sets stdin to a memory-backed file.
int error = fuzzer_set_stdin(NULL, 0);
if (error) {
fprintf(stderr, "set_stdin() failed: error code %d\n", error);
abort();
}
// Determine the max page size based on our cups header.
const size_t maxPageSize = header.cupsHeight * header.cupsBytesPerLine;
// Grab some bytes from the fuzz data for the options to be passed into the
// filter.
size_t offset = 0;
const size_t max_options_size = 64;
const size_t options_size = MIN(size, max_options_size);
char options[max_options_size + 1];
strncpy(options, data, options_size);
options[options_size] = '\0';
size -= options_size;
offset += options_size;
// Writes the raster content to stdin for the filter to consume.
// Stdin is a memory-backed file.
cups_raster_t *raster = cupsRasterOpen(STDIN_FILENO, CUPS_RASTER_WRITE);
while (size > 0) {
// Don't write more than the max size specified by our header.
const size_t numToWrite = MIN(size, maxPageSize);
cupsRasterWriteHeader2(raster, &header);
cupsRasterWritePixels(raster, (unsigned char *)(data + offset), numToWrite);
size -= numToWrite;
offset += numToWrite;
}
cupsRasterClose(raster);
fuzzer_rewind_stdin();
char *argv[] = {/*uri*/ "", /*job id*/ "1",
/*user*/ "chronos", /*title*/ "Untitled",
/*copies*/ "1", /*options*/ options};
// This command may fail and return a non-zero error code
// if the input raster header is malformed.
EpsonEscprPrintJob(sizeof(argv) / sizeof(argv[0]), argv);
return 0;
}