OpenPrinting / OpenPrinting/libcupsfilters

cfFilterGhostscript: duplex DM3 (Rotated) emits -dcupsInteger1=4294967295; Ghostscript appleraster rangecheck

Open Beginner friendly
#222 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
17
Forks
71
Avg merge
2d 17h
Merged PRs (30d)
13

Description

Summary

cfFilterGhostscript() formats PWG/Apple Raster duplex transform fields with %u. For printers that advertise URF duplex mode DM3 (Rotated), raster_base_header() stores CrossFeedTransform/FeedTransform as -1 in the unsigned cupsInteger[1] / cupsInteger[2] slots. That becomes 4294967295 on the Ghostscript command line. Ghostscript's appleraster device reads those parameters with param_read_int() (signed 32-bit), so the job dies with:

ERROR: Error setting cupsInteger1 ...
Unrecoverable error: rangecheck in .putdeviceprops

CUPS then pauses the queue (Job processing failed.). Simplex jobs work. Duplex PDF → URF jobs fail every time.

This is not a cups-browsed or CUPS daemon bug. Driverless IPP just happens to take this path because the printer does not accept PDF.

Environment

  • Arch Linux (Omarchy 4.0.1), aarch64
  • libcupsfilters 2.2.1-2
  • cups-filters 2.0.1-2
  • cups-browsed 2.1.1-1
  • CUPS 2.4.19
  • Ghostscript 10.07.1
  • Printer: EPSON ET-16650 Series (driverless IPP / Apple Raster)
  • urf-supported includes DM3 (Rotated duplex)

Printer document formats: image/pwg-raster, image/urf, image/jpeg, application/vnd.epson.escpr (no PDF).

How to reproduce

  1. Use a driverless IPP queue whose printer advertises URF duplex mode DM3.
  2. Print a PDF with duplex long-edge (Duplex=DuplexNoTumble / sides=two-sided-long-edge).
  3. Filter chain: pdftopdfcfFilterGhostscript (-sDEVICE=appleraster) → IPP backend.

CUPS log from a real job:

FINAL_CONTENT_TYPE=image/urf
argv[5]: ... Duplex=DuplexNoTumble ... InputSlot=Main ... PageSize=Letter ...

cfFilterGhostscript: Ghostscript command line: gs ... -sDEVICE=appleraster ... -dDuplex ...
  -dcupsInteger1=4294967295 -dcupsInteger2=4294967295 -dcupsInteger8=4
  -scupsPageSizeName=Letter -scupsBackSideOrientation=Rotated ...

cfFilterGhostscript: Error setting cupsInteger1 ...
cfFilterGhostscript: Unrecoverable error: rangecheck in .putdeviceprops
Job processing failed.

cupsfilter with only a PPD does not reproduce this: that path never loads printer IPP attributes, so it never applies the DM3 transforms.

It does reproduce with libcupsfilters against the live printer:

data.printer_attrs = cfGetPrinterAttributes("ipp://printer/ipp/print", NULL, 0, NULL, 0, 0);
data.num_options = cupsAddOption("Duplex", "DuplexNoTumble", ...);
cfRasterPrepareHeader(&h, &data, CF_FILTER_OUT_FORMAT_APPLE_RASTER, ...);
/* h.cupsInteger[1] == 4294967295u, (int)h.cupsInteger[1] == -1 */
cfFilterGhostscript(...); /* fails with the Ghostscript line above */

On this Epson that printed:

urf-supported: ... DM3 ...
Duplex=1 Tumble=0
cupsInteger[1] unsigned=4294967295 signed=-1
cupsInteger[2] unsigned=4294967295 signed=-1
cfFilterGhostscript status=1

Isolated Ghostscript confirmation (no printer required)

# Fails (what libcupsfilters currently emits)
gs -dQUIET -dSAFER -dNOPAUSE -dBATCH -sDEVICE=appleraster \
  -sOutputFile=/dev/null -r600x600 \
  -dDEVICEWIDTHPOINTS=612 -dDEVICEHEIGHTPOINTS=792 \
  -dcupsInteger1=4294967295 -dcupsInteger2=4294967295 \
  -c quit
# ERROR: Error setting cupsInteger1 ...
# Unrecoverable error: rangecheck in .putdeviceprops

# Succeeds (the intended PWG transform values)
gs -dQUIET -dSAFER -dNOPAUSE -dBATCH -sDEVICE=appleraster \
  -sOutputFile=/dev/null -r600x600 \
  -dDEVICEWIDTHPOINTS=612 -dDEVICEHEIGHTPOINTS=792 \
  -dcupsInteger1=-1 -dcupsInteger2=-1 \
  -c quit
# INFO: Rendering completed

The full cfFilterGhostscript command line behaves the same way: 4294967295 → exit 255 and empty output; -1 → 76 KB Apple Raster from a 2-page PDF.

Root cause

In cupsfilters/raster.c (raster_base_header()), PWG/Apple Raster duplex with Rotated / DM3 and long-edge (Tumble == CUPS_FALSE) does:

h->cupsInteger[1] = -1;  /* CrossFeedTransform */
h->cupsInteger[2] = -1;  /* FeedTransform */

cupsInteger[] is unsigned, so those become UINT32_MAX. That is the usual two's-complement encoding of -1 in a PWG Raster header and is correct inside the raster header.

In cupsfilters/ghostscript.c (header_to_gs_args()):

for (i = 0; i <= 15; i ++)
  if (h->cupsInteger[i])
  {
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsInteger%d=%u",
             i, (unsigned)(h->cupsInteger[i]));
    cupsArrayAdd(gs_args, strdup(tmpstr));
  }

UINT32_MAX is non-zero, so it is passed as -dcupsInteger1=4294967295. Ghostscript cups/gdevcups.c uses param_read_int() for cupsIntegerN, which cannot hold that value.

cupsInteger8=4 in the failing command is print-quality (normal) and is fine.

Suggested fix

Format the Ghostscript integers as signed, which turns the stored UINT32_MAX back into -1:

snprintf(tmpstr, sizeof(tmpstr), "-dcupsInteger%d=%d",
         i, (int)h->cupsInteger[i]);

That matches how these fields are used as PWG CrossFeed/Feed transforms (±1). Passing -dcupsInteger1=-1 was verified to make Ghostscript 10.07.1 accept the device setup and rasterize the PDF.

Expected

Duplex driverless PDF → Apple/PWG Raster jobs complete. CUPS should not pause the printer.

Actual

Ghostscript aborts during device setup. The job fails and CUPS stops the queue until it is re-enabled.


Disclosure: Debugged, documented, and drafted by Grok (xAI). The failure was reproduced on this machine against libcupsfilters 2.2.1 and Ghostscript 10.07.1; the suggested %d / (int) change was checked with the same Ghostscript command line ( 4294967295 fails, -1 rasterizes). A human is submitting the report.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in cupsfilters/ghostscript.c at header_to_gs_args(), then compare its formatting with the signed transform values described in cupsfilters/raster.c and raster_base_header(). Verify the generated Ghostscript arguments with the isolated appleraster commands: DM3 values should be passed as -1 rather than 4294967295, and duplex PDF-to-Apple/PWG Raster jobs should complete without the rangecheck failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
backend
Issue type
Bug
Difficulty
1/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
85/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.