classification
Title: SSLObject breaks read semantics
Type: Stage:
Components: Library (Lib) Versions: Python 2.4
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: janssen Nosy List: ellisj, janssen
Priority: normal Keywords:

Created on 2005-09-14 22:28 by ellisj, last changed 2008-09-05 17:43 by ellisj. This issue is now closed.

Messages (8)
msg60815 - (view) Author: Jonathan Ellis (ellisj) Date: 2005-09-14 22:28
f = socket.ssl(sock)
f.read(n)

doesn't always return n bytes, even if the connection
remains open!  in particular, it seems to reproducibly
return less than n bytes if the read would span the
boundary between units of 16KB of data.

We've had to work around this with code like the following:

        pieces = []
        while n > 0:
            got = self.realfile.read(n)
            if not got:
                break
            pieces.append(got)
            n -= len(got)
        return ''.join(pieces)
msg72451 - (view) Author: Bill Janssen (janssen) * (Python committer) Date: 2008-09-04 01:33
I think I'm going to close this.  file.read(N) is not guaranteed to
return N bytes, it's guaranteed to return at most N bytes.
msg72481 - (view) Author: Jonathan Ellis (ellisj) Date: 2008-09-04 05:05
This is incorrect.  Perhaps you are thinking of a raw socket read; a 
_file-like-object_ read is supposed to return the amount of data 
requested, unless (a) the socket is in non-blocking mode, or (b) if EOF 
is reached first.  Normal socket.makefile observes this, but SSLObject 
does not.
msg72482 - (view) Author: Jonathan Ellis (ellisj) Date: 2008-09-04 05:07
s/raw socket read/raw socket recv/
msg72516 - (view) Author: Bill Janssen (janssen) * (Python committer) Date: 2008-09-04 20:03
The way I read the documentation, file.read() (and that's what we're
talking about) is still not guaranteed to read all the bytes of the
file.  But, you're right, that is the accepted semantics.  So the
documentation should change, too.

However, the "read" method on an SSLSocket, which is not a file()
subclass, is *not* guaranteed to return N bytes, it's guaranteed to
return at most N bytes.  Call "makefile" on SSLSocket if you need a
file-like object.
msg72518 - (view) Author: Jonathan Ellis (ellisj) Date: 2008-09-04 20:14
Here is the exact SSLObject.read documentation from 2.5 (although the 
bug was filed against 2.4, and 2.6 will be out soon, the docs are the 
same):

-----

read([n])

If n is provided, read n bytes from the SSL connection, otherwise read 
until EOF. The return value is a string of the bytes read.

-----

This is not ambiguous.  Similarly, help(file.read) is not ambiguous.  
(The "at most" part in the first line of file.read is later explained 
to apply to non-blocking reads.)

If you want to claim "well, it's not a file-like object" then (a) it 
shouldn't have file-like methods (socket-like send and recv are the 
obvious choices instead of write and read), (b) you need to fix your 
docs.  But since god knows how many programs are out there expecting 
the semantics explained by the existing docs, I think just fixing the 
bug in the code is better than defining away the problem.

(Obviously socket.makefile won't work on an object that doesn't 
implement a socket-like interface, so that's a non-option.)
msg72610 - (view) Author: Bill Janssen (janssen) * (Python committer) Date: 2008-09-05 17:20
Ah, sorry.  I was looking at the 2.6 documentation, not the 2.5
documentation.  In 2.6 (which is what the new SSL code is for),
documentation of socket.ssl has been removed entirely, along with the
text that you cite, although the functionality from 2.5 socket.ssl is
still provided for backwards compatibility.  In 2.6, the ssl.SSLSocket
type is a subclass of socket.socket, so you call "makefile" on it to get
a file-like object for reading and writing.

If you'd like to submit a patch for 2.5 and 2.6, I think this is
backwards-compatible enough to qualify as a fix, not a feature enhancement.
msg72613 - (view) Author: Jonathan Ellis (ellisj) Date: 2008-09-05 17:43
Ah, great.  I was wondering why you kept talking about SSLSocket 
instead of SSLObject.  "New API in 2.6" is good enough for me.  Thanks!
History
Date User Action Args
2008-09-05 17:43:05ellisjsetmessages: + msg72613
2008-09-05 17:20:13janssensetmessages: + msg72610
2008-09-04 20:14:43ellisjsetmessages: + msg72518
2008-09-04 20:03:22janssensetmessages: + msg72516
2008-09-04 05:07:11ellisjsetmessages: + msg72482
2008-09-04 05:05:14ellisjsetmessages: + msg72481
2008-09-04 01:33:47janssensetstatus: open -> closed
2008-09-04 01:33:37janssensetresolution: rejected
messages: + msg72451
2008-06-30 01:11:03janssensetassignee: janssen
nosy: + janssen
2005-09-14 22:28:27ellisjcreate