[pycrypto] Run test suite with /dev/random

Dwayne C. Litzenberger dlitz at dlitz.net
Fri Jan 27 13:13:47 EST 2012

On Fri, Jan 20, 2012 at 05:20:57PM +0100, Sebastian Ramacher wrote:
>Nevertheless there is still an issue in pycrypto left. The assumption that 
>read always returns the amount of data requested if there is enough 
>available is not true. If the process is interrupted by a signal read will 
>return less. At least that's the case for Python3.

That assumption is *correct*.  A Python file object's read() method always 
returns the requested amount of data, except in two cases:

     1. Non-blocking I/O is selected; or
     2. End-of-file is reached.

You are confusing this with the read(2) syscall, which *can* return fewer 
bytes than requested if the process receives a signal.

Here's the relevant Python documentation:

> file.read([<size>])
>     Read at most <size> bytes from the file (less if the read hits EOF 
>     before obtaining <size> bytes). If the <size> argument is negative 
>     or omitted, read all data until EOF is reached. The bytes are 
>     returned as a string object. An empty string is returned when EOF 
>     is encountered immediately. (For certain files, like ttys, it makes 
>     sense to continue reading after an EOF is hit.) Note that this 
>     method may call the underlying C function fread() more than once in 
>     an effort to acquire as close to <size> bytes as possible. Also 
>     note that when in non-blocking mode, less data than was requested 
>     may be returned, even if no <size> parameter was given.
>     Note: This function is simply a wrapper for the underlying fread() 
>     C function, and will behave the same in corner cases, such as 
>     whether the EOF value is cached.
> -- http://docs.python.org/library/stdtypes.html#file-objects

You've discovered a Python3 bug.  Good work. :)

I checked, and this works correctly in Python 2.  The problem seems to be 
(at least in Python 3.2.2) that file.read is no longer a wrapper around 
fread(), and Python3's implementation doesn't retry read() calls like it's 
supposed to.

I've attached a C program that allows you to test the behaviour of fread().  
Here's how to test it (using bash):

    1. Compile it:
        gcc -O2 -o freadtest freadtest.c
    2. Run it:
        ./freadtest /dev/urandom
    3. Press Ctrl-Z to suspend it.
    4. Type "fg" to resume the process
    5. You should not see any output.

So, the problem is that Python3's current implementation of file.read() 
doesn't behave as documented, and it doesn't behave like it did in Python 

I suggest reporting this bug against Python itself.

- Dwayne

Dwayne C. Litzenberger <dlitz at dlitz.net>
  OpenPGP: 19E1 1FE8 B3CF F273 ED17  4A24 928C EC13 39C2 5CF7
-------------- next part --------------
A non-text attachment was scrubbed...
Name: freadtest.c
Type: text/x-csrc
Size: 1290 bytes
Desc: not available
URL: <http://lists.dlitz.net/pipermail/pycrypto/attachments/20120127/d7831cf3/attachment.c>

More information about the pycrypto mailing list