Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ EXTRA_DIST = \

EXTRA_DIST += \
cupsfilters/test-pclm-overflow.sh \
cupsfilters/test-pwgtopdf-bit-row.sh \
data/makePDFfromPS.sh \
data/classified.ps \
data/confidential.ps \
Expand Down Expand Up @@ -93,6 +94,7 @@ lib_LTLIBRARIES = libcupsfilters.la
check_SCRIPTS = \
cupsfilters/testfilters.sh \
cupsfilters/test-pclm-overflow.sh \
cupsfilters/test-pwgtopdf-bit-row.sh \
cupsfilters/test-pdftoraster-copy-height.sh

check_PROGRAMS = \
Expand All @@ -117,6 +119,7 @@ TESTS = \
test-ps \
cupsfilters/testfilters.sh \
cupsfilters/test-pclm-overflow.sh \
cupsfilters/test-pwgtopdf-bit-row.sh \
cupsfilters/test-pdftoraster-copy-height.sh

# testcmyk # fails as it opens some image.ppm which is nowerhe to be found.
Expand Down
15 changes: 7 additions & 8 deletions cupsfilters/pwgtopdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ typedef unsigned char *(*convert_function)(unsigned char *src,
// Bit conversion function
typedef unsigned char *(*bit_convert_function)(unsigned char *src,
unsigned char *dst,
unsigned int pixels);
unsigned int bytes);

typedef struct pwgtopdf_doc_s // **** Document information ****
{
Expand Down Expand Up @@ -272,12 +272,12 @@ void free_pdf_info(struct pdf_info *info)
static unsigned char* // O - output string of pixels
invert_bits(unsigned char *src, // I - source chars
unsigned char *dst, // O - destination chars
unsigned int pixels) // I - pixels
unsigned int bytes) // I - bytes
{
unsigned int i;

// Invert black to grayscale...
for (i = pixels, dst = src; i > 0; i --, dst ++)
for (i = bytes, dst = src; i > 0; i --, dst ++)
*dst = ~*dst;

return (dst);
Expand All @@ -286,13 +286,14 @@ invert_bits(unsigned char *src, // I - source chars

static unsigned char* // O - Output string of bits
no_bit_conversion(unsigned char *src, // I - Source chars
unsigned char *dst, // O - destination chars
unsigned int pixels) // I - Pixesl
unsigned char *dst, // O - destination chars
unsigned int bytes) // I - bytes
{
return (src);
}



//
// Color conversion functions
//
Expand Down Expand Up @@ -1634,7 +1635,7 @@ convert_raster(cups_raster_t *ras,
#endif

// perform bit operations if necessary
doc->bit_function(PixelBuffer, buff, width);
doc->bit_function(PixelBuffer, buff, bpl);

// write lines and color convert when necessary
pdf_set_line(info, cur_line, doc->conversion_function(PixelBuffer,
Expand Down Expand Up @@ -2068,5 +2069,3 @@ cfFilterPWGToPDF(int inputfd, // I - File descriptor input stream
return (ret);
}



188 changes: 188 additions & 0 deletions cupsfilters/test-pwgtopdf-bit-row.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD_ROOT="$(cd "${ROOT}/.." && pwd)"
LIBTOOL="${BUILD_ROOT}/libtool"
CC="${CC:-cc}"
SAN_FLAGS="${SAN_FLAGS:--fsanitize=address -fno-omit-frame-pointer}"
PKG_CFLAGS="$(pkg-config --cflags lcms2 pdfio 2>/dev/null || true)"
PKG_LIBS="$(pkg-config --libs lcms2 pdfio 2>/dev/null || true)"

if pkg-config --exists cups 2>/dev/null; then
PKG_CFLAGS+=" $(pkg-config --cflags cups)"
PKG_LIBS+=" $(pkg-config --libs cups)"
elif pkg-config --exists cups3 2>/dev/null; then
PKG_CFLAGS+=" $(pkg-config --cflags cups3)"
PKG_LIBS+=" $(pkg-config --libs cups3)"
elif command -v cups-config >/dev/null 2>&1; then
PKG_CFLAGS+=" $(cups-config --cflags)"
PKG_LIBS+=" $(cups-config --libs)"
fi

# The compiler accepting -fsanitize=address is not enough: qemu-user builds
# can link the runtime but abort while initializing it. Run a trivial probe so
# those emulated CI legs skip instead of reporting a product-code failure.
asan_probe="$(mktemp "${TMPDIR:-/tmp}/asan-probe.XXXXXX")"
if ! printf 'int main(void){return 0;}\n' \
| "${CC}" ${SAN_FLAGS} -x c - -o "${asan_probe}" >/dev/null 2>&1 \
|| ! "${asan_probe}" >/dev/null 2>&1; then
echo "AddressSanitizer not usable in this environment; skipping." >&2
rm -f "${asan_probe}"
exit 77
fi
rm -f "${asan_probe}"

if [[ ! -x "${LIBTOOL}" ]]; then
echo "libtool helper not found at ${LIBTOOL}" >&2
exit 99
fi

WORKDIR="$(mktemp -d "${TMPDIR:-/tmp}/pwgtopdf-bit-row.XXXXXX")"
cleanup() {
rm -rf "${WORKDIR}"
}
trap cleanup EXIT

INPUT_PWG="${WORKDIR}/black-1bit.pwg"
OUTPUT_PDF="${WORKDIR}/output.pdf"
GENERATOR_SRC="${WORKDIR}/make-pwg.c"
GENERATOR_BIN="${WORKDIR}/make-pwg"
HARNESS_SRC="${WORKDIR}/run-filter.c"
HARNESS_OBJ="${WORKDIR}/run-filter.lo"
HARNESS_BIN="${WORKDIR}/run-filter"
RUN_LOG="${WORKDIR}/run.log"

cat > "${GENERATOR_SRC}" <<'EOF'
#include <cups/raster.h>
#include "cupsfilters/libcups2-private.h"
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv) {
cups_page_header_t header;
unsigned char row[16] = {0};
cups_raster_t *ras;
int fd;

if (argc != 2)
return 1;

fd = open(argv[1], O_CREAT | O_TRUNC | O_WRONLY, 0644);
if (fd < 0)
return 1;

ras = cupsRasterOpen(fd, CUPS_RASTER_WRITE);
if (!ras) {
close(fd);
return 1;
}

memset(&header, 0, sizeof(header));
header.HWResolution[0] = header.HWResolution[1] = 300;
header.PageSize[0] = 612;
header.PageSize[1] = 792;
header.cupsPageSize[0] = 612.0f;
header.cupsPageSize[1] = 792.0f;
header.cupsImagingBBox[2] = 612.0f;
header.cupsImagingBBox[3] = 792.0f;
header.cupsWidth = 128;
header.cupsHeight = 1;
header.cupsBitsPerColor = 1;
header.cupsBitsPerPixel = 1;
header.cupsNumColors = 1;
header.cupsBytesPerLine = sizeof(row);
header.cupsColorOrder = CUPS_ORDER_CHUNKED;
header.cupsColorSpace = CUPS_CSPACE_K;

if (!cupsRasterWriteHeader(ras, &header) ||
cupsRasterWritePixels(ras, row, sizeof(row)) != sizeof(row)) {
cupsRasterClose(ras);
close(fd);
return 1;
}

cupsRasterClose(ras);
close(fd);
return 0;
}
EOF

cat > "${HARNESS_SRC}" <<'EOF'
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

// Compile the production implementation with ASan even when the surrounding
// project build is not sanitized.
#include "cupsfilters/pwgtopdf.c"

int main(int argc, char **argv) {
cf_filter_data_t data;
cf_filter_out_format_t outformat = CF_FILTER_OUT_FORMAT_PDF;
int inputfd;
int outputfd;
int result;

if (argc != 3)
return 1;

inputfd = open(argv[1], O_RDONLY);
outputfd = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY, 0644);
if (inputfd < 0 || outputfd < 0)
return 1;

memset(&data, 0, sizeof(data));
data.content_type = (char *)"image/pwg-raster";
data.final_content_type = (char *)"application/pdf";

result = cfFilterPWGToPDF(inputfd, outputfd, 1, &data, &outformat);
close(inputfd);
close(outputfd);
return result;
}
EOF

"${CC}" -std=c11 -O0 ${SAN_FLAGS} -o "${GENERATOR_BIN}" \
-I"${BUILD_ROOT}" ${PKG_CFLAGS} "${GENERATOR_SRC}" ${PKG_LIBS}
"${GENERATOR_BIN}" "${INPUT_PWG}"

"${LIBTOOL}" --mode=compile --tag=CC "${CC}" -std=gnu11 -O0 \
-D_GNU_SOURCE ${SAN_FLAGS} \
-I"${BUILD_ROOT}" -I"${BUILD_ROOT}/cupsfilters" ${PKG_CFLAGS} \
-c "${HARNESS_SRC}" -o "${HARNESS_OBJ}" >/dev/null

"${LIBTOOL}" --mode=link --tag=CC "${CC}" ${SAN_FLAGS} "${HARNESS_OBJ}" \
"${BUILD_ROOT}/libcupsfilters.la" ${PKG_LIBS} -lm \
-o "${HARNESS_BIN}" >/dev/null

ASAN_OPTS="${ASAN_OPTIONS:-detect_leaks=0,abort_on_error=0}"
set +e
"${LIBTOOL}" --mode=execute env \
DYLD_LIBRARY_PATH="${BUILD_ROOT}/.libs${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}}" \
ASAN_OPTIONS="${ASAN_OPTS}" \
"${HARNESS_BIN}" "${INPUT_PWG}" "${OUTPUT_PDF}" >"${RUN_LOG}" 2>&1
STATUS=$?
set -e

if [[ ${STATUS} -ne 0 ]]; then
cat "${RUN_LOG}" >&2
echo "pwgtopdf exited with status ${STATUS}" >&2
exit 1
fi

if grep -q "AddressSanitizer" "${RUN_LOG}"; then
cat "${RUN_LOG}" >&2
echo "AddressSanitizer reported a memory error" >&2
exit 1
fi

if [[ ! -s "${OUTPUT_PDF}" ]]; then
echo "No PDF output generated" >&2
exit 1
fi

exit 0
Loading