Hello all,

For pycups method, cups.writeRequestData, there is a bug that will corrupt binary data when streamed through this method.

This python code will expose the problem:

import cups
x = None

conn = cups.Connection()

id = conn.createJob('printer', 'blah', { 'document-format': cups.CUPS_FORMAT_AUTO })
conn.startDocument('printer', id, 'asdfasd', cups.CUPS_FORMAT_AUTO, 1)

with open('test.pdf', 'rb') as f:
    while True:
        x = f.read(1024)
        if len(x):
            conn.writeRequestData(x, len(x))
        else:
            break

conn.finishDocument('printer')

The printer will print out a sheet with the text:

PDF Error 10: PostScript: Error: IOERROR
Assert FaileD: rc == curStrLen

If you take the print queue down and print the same file with lpr -P printer, the md5sums in /var/spool/cups are different.  Each lpr command produces a queued file with the same hash as the original file.  Each file printed through the API will have a different sum each time.

The issue is caused by this line in the code:

buffer = strdup(PyBytes_AsString (buffer_obj));

The strdup detects a null in the Python byte array and ends the copy.  This causes a buffer overrun when "status = cupsWriteRequestData(self->http, buffer, length);" is called.  This is because the buffer might only have 120 bytes in it, and the length is equal to, says, 8192. 

I switched over to memcpy, and malloc'd a separate buffer.  I choose memcpy as this method is not overrun safe.  The caller must mind his or her own buffer size.  The method now works with jpgs, pdfs, and regular text files.

Feel free to make my code better as my C is a bit rusty.

Doug