diff options
| author | Jannis Leidel <jannis@leidel.info> | 2011-06-28 10:17:56 +0000 |
|---|---|---|
| committer | Jannis Leidel <jannis@leidel.info> | 2011-06-28 10:17:56 +0000 |
| commit | a6cd78662e72188555027a459cbff2564d72a221 (patch) | |
| tree | e072e1aed9c6e139fe1c79a4a3f56c80c2a54c80 /django | |
| parent | 0278947128cf478b47b0bc87ac0c2de0405b3d2a (diff) | |
Fixed #15785 -- Stopped HttpRequest.read() from reading beyond the end of a wsgi.input stream and removed some redundant code in the multipartparser. Thanks, tomchristie, grahamd and isagalaev.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16479 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django')
| -rw-r--r-- | django/core/handlers/wsgi.py | 25 | ||||
| -rw-r--r-- | django/http/__init__.py | 12 | ||||
| -rw-r--r-- | django/http/multipartparser.py | 36 |
3 files changed, 11 insertions, 62 deletions
diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py index 2acb3b1ee7..14420fa760 100644 --- a/django/core/handlers/wsgi.py +++ b/django/core/handlers/wsgi.py @@ -135,26 +135,11 @@ class WSGIRequest(http.HttpRequest): self.META['SCRIPT_NAME'] = script_name self.method = environ['REQUEST_METHOD'].upper() self._post_parse_error = False - if type(socket._fileobject) is type and isinstance(self.environ['wsgi.input'], socket._fileobject): - # Under development server 'wsgi.input' is an instance of - # socket._fileobject which hangs indefinitely on reading bytes past - # available count. To prevent this it's wrapped in LimitedStream - # that doesn't read past Content-Length bytes. - # - # This is not done for other kinds of inputs (like flup's FastCGI - # streams) beacuse they don't suffer from this problem and we can - # avoid using another wrapper with its own .read and .readline - # implementation. - # - # The type check is done because for some reason, AppEngine - # implements _fileobject as a function, not a class. - try: - content_length = int(self.environ.get('CONTENT_LENGTH', 0)) - except (ValueError, TypeError): - content_length = 0 - self._stream = LimitedStream(self.environ['wsgi.input'], content_length) - else: - self._stream = self.environ['wsgi.input'] + try: + content_length = int(self.environ.get('CONTENT_LENGTH')) + except (ValueError, TypeError): + content_length = 0 + self._stream = LimitedStream(self.environ['wsgi.input'], content_length) self._read_started = False def get_full_path(self): diff --git a/django/http/__init__.py b/django/http/__init__.py index cf1eb0d9e2..e667f6a9fc 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -308,17 +308,7 @@ class HttpRequest(object): if not hasattr(self, '_raw_post_data'): if self._read_started: raise Exception("You cannot access raw_post_data after reading from request's data stream") - try: - content_length = int(self.META.get('CONTENT_LENGTH', 0)) - except (ValueError, TypeError): - # If CONTENT_LENGTH was empty string or not an integer, don't - # error out. We've also seen None passed in here (against all - # specs, but see ticket #8259), so we handle TypeError as well. - content_length = 0 - if content_length: - self._raw_post_data = self.read(content_length) - else: - self._raw_post_data = self.read() + self._raw_post_data = self.read() self._stream = StringIO(self._raw_post_data) return self._raw_post_data raw_post_data = property(_get_raw_post_data) diff --git a/django/http/multipartparser.py b/django/http/multipartparser.py index 63203a4581..477a08c05a 100644 --- a/django/http/multipartparser.py +++ b/django/http/multipartparser.py @@ -33,7 +33,7 @@ class MultiPartParser(object): A rfc2388 multipart/form-data parser. ``MultiValueDict.parse()`` reads the input stream in ``chunk_size`` chunks - and returns a tuple of ``(MultiValueDict(POST), MultiValueDict(FILES))``. If + and returns a tuple of ``(MultiValueDict(POST), MultiValueDict(FILES))``. """ def __init__(self, META, input_data, upload_handlers, encoding=None): """ @@ -65,14 +65,11 @@ class MultiPartParser(object): raise MultiPartParserError('Invalid boundary in multipart: %s' % boundary) - # # Content-Length should contain the length of the body we are about # to receive. - # try: content_length = int(META.get('HTTP_CONTENT_LENGTH', META.get('CONTENT_LENGTH',0))) except (ValueError, TypeError): - # For now set it to 0; we'll try again later on down. content_length = 0 if content_length < 0: @@ -110,12 +107,10 @@ class MultiPartParser(object): if self._content_length == 0: return QueryDict(MultiValueDict(), encoding=self._encoding), MultiValueDict() - limited_input_data = LimitBytes(self._input_data, self._content_length) - # See if the handler will want to take care of the parsing. # This allows overriding everything if somebody wants it. for handler in handlers: - result = handler.handle_raw_input(limited_input_data, + result = handler.handle_raw_input(self._input_data, self._meta, self._content_length, self._boundary, @@ -128,7 +123,7 @@ class MultiPartParser(object): self._files = MultiValueDict() # Instantiate the parser and stream: - stream = LazyStream(ChunkIter(limited_input_data, self._chunk_size)) + stream = LazyStream(ChunkIter(self._input_data, self._chunk_size)) # Whether or not to signal a file-completion at the beginning of the loop. old_field_name = None @@ -225,10 +220,10 @@ class MultiPartParser(object): exhaust(stream) except StopUpload, e: if not e.connection_reset: - exhaust(limited_input_data) + exhaust(self._input_data) else: # Make sure that the request data is all fed - exhaust(limited_input_data) + exhaust(self._input_data) # Signal that the upload has completed. for handler in handlers: @@ -390,27 +385,6 @@ class ChunkIter(object): def __iter__(self): return self -class LimitBytes(object): - """ Limit bytes for a file object. """ - def __init__(self, fileobject, length): - self._file = fileobject - self.remaining = length - - def read(self, num_bytes=None): - """ - Read data from the underlying file. - If you ask for too much or there isn't anything left, - this will raise an InputStreamExhausted error. - """ - if self.remaining <= 0: - raise InputStreamExhausted() - if num_bytes is None: - num_bytes = self.remaining - else: - num_bytes = min(num_bytes, self.remaining) - self.remaining -= num_bytes - return self._file.read(num_bytes) - class InterBoundaryIter(object): """ A Producer that will iterate over boundaries. |
