[pycrypto] Run test suite with /dev/random

Dwayne C. Litzenberger dlitz at dlitz.net
Mon Jan 30 23:45:40 EST 2012


On Sat, Jan 28, 2012 at 02:14:10AM +0100, Sebastian Ramacher wrote:
>There is no file object anymore. The I/O stack got rewritten in Python 3.  
>If open would be called without buffering=0, all the assumptions would be 
>correct again (and one would have fread like behavior). But since 
>buffering equals 0, open returns a FileIO instance. And FileIO.read just 
>behaves as the underlying syscall which is read(2). [1, 2]
>
>[1] http://docs.python.org/py3k/library/io.html#raw-i-o
>[2] http://docs.python.org/py3k/library/io.html#io.RawIOBase

What the hell?  So, open() returns an object that *isn't* a file-like 
object (according to the definition of a file-like object) just because I 
asked for a zero-length buffer?  What happened to "explicit is better than 
implicit"?  "Special cases aren't special enough to break the rules"?

*Sigh* I still consider this to be a bug in Python, but I guess it's 
unlikely to ever be fixed... :-/

Ok, I'm willing to accept a patch that implements your workaround, if you 
can address a few remaining issues:

1. BlockingIOError needs to be handled.  If the signal occurs immediately 
    after the read(2) syscall is invoked, it will set errno=EAGAIN and 
    Python will raise BlockingIOError.  (At least, that's what the 
    documentation says.)

2. If EOF is encountered for some reason, your loop would never terminate.  
    This shouldn't happen normally, but the RNG is a critical piece of 
    essentially untestable code, so it's okay to code it a little more
    defensively than usual.  (Who knows?  We might encounter a broken 
    /dev/urandom implementation, or somebody might build a broken chroot 
    environment).

    If DevURandomRNG._read gets an EOF, it should behave like a normal 
    file-like object.  That is, it should return the truncated string, and 
    subsequently always return b"".  Basically, if self.__file.read(...) == 
    b"", then return data.

    There's no BlockingIOError defined in Python 2.x, so that will need to 
    be taken into account.

3. Please also include a comment in the code that explains why this needs 
    to be done.

Cheers,
- Dwayne

P.S.  Thank you for tracking this down.  As a packager, I guess you receive 
more than your fair share of flak for problems created by other people!  
Even though I enthusiastically reject some of your patches, I (and probably 
many users of PyCrypto) appreciate the work that you are doing. :)

-- 
Dwayne C. Litzenberger <dlitz at dlitz.net>
  OpenPGP: 19E1 1FE8 B3CF F273 ED17  4A24 928C EC13 39C2 5CF7


More information about the pycrypto mailing list