Skip to content

Commit

Permalink
Replace shared global _empty_stream with separate instances
Browse files Browse the repository at this point in the history
If a test closed the _empty_stream, subsequent requests could reuse this
closed stream, causing request.get_data() and other methods to fail.
  • Loading branch information
chromakode committed Aug 3, 2018
1 parent ac230a2 commit baf2051
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 12 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Expand Up @@ -71,6 +71,11 @@ Unreleased
`#795`_)
- The test client raises a ``ValueError`` if a query string argument
would overwrite a query string in the path. (`#1338`_)
- :class:`~test.EnvironBuilder`, :class:`~datastructures.FileStorage`,
and :func:`wsgi.get_input_stream` no longer share a global
``_empty_stream`` instance. This improves test isolation by preventing
cases where closing the stream in one request would affect other usages.
(`#1340`_)

.. _`#209`: https://github.com/pallets/werkzeug/pull/209
.. _`#609`: https://github.com/pallets/werkzeug/pull/609
Expand Down Expand Up @@ -104,6 +109,7 @@ Unreleased
.. _`#1316`: https://github.com/pallets/werkzeug/pull/1316
.. _`#1318`: https://github.com/pallets/werkzeug/pull/1318
.. _`#1338`: https://github.com/pallets/werkzeug/pull/1338
.. _`#1340`: https://github.com/pallets/werkzeug/pull/1340


Version 0.14.1
Expand Down
5 changes: 2 additions & 3 deletions werkzeug/_internal.py
Expand Up @@ -15,12 +15,11 @@
from datetime import datetime, date
from itertools import chain

from werkzeug._compat import iter_bytes, text_type, BytesIO, int_to_byte, \
range_type, integer_types
from werkzeug._compat import iter_bytes, text_type, int_to_byte, range_type, \
integer_types


_logger = None
_empty_stream = BytesIO()
_signature_cache = WeakKeyDictionary()
_epoch_ord = date(1970, 1, 1).toordinal()
_cookie_params = set((b'expires', b'path', b'comment',
Expand Down
10 changes: 5 additions & 5 deletions werkzeug/datastructures.py
Expand Up @@ -15,10 +15,10 @@
from itertools import repeat
from collections import Container, Iterable, MutableSet

from werkzeug._internal import _missing, _empty_stream
from werkzeug._compat import iterkeys, itervalues, iteritems, iterlists, \
PY2, text_type, integer_types, string_types, make_literal_wrapper, \
to_native
from werkzeug._internal import _missing
from werkzeug._compat import BytesIO, iterkeys, itervalues, iteritems, \
iterlists, PY2, text_type, integer_types, string_types, \
make_literal_wrapper, to_native
from werkzeug.filesystem import get_filesystem_encoding


Expand Down Expand Up @@ -2639,7 +2639,7 @@ def __init__(self, stream=None, filename=None, name=None,
content_type=None, content_length=None,
headers=None):
self.name = name
self.stream = stream or _empty_stream
self.stream = stream or BytesIO()

# if no filename is provided we can attempt to get the filename
# from the stream object passed. There we have to be careful to
Expand Down
4 changes: 2 additions & 2 deletions werkzeug/test.py
Expand Up @@ -28,7 +28,7 @@
from werkzeug._compat import iterlists, iteritems, itervalues, to_bytes, \
string_types, text_type, reraise, wsgi_encoding_dance, \
make_literal_wrapper
from werkzeug._internal import _empty_stream, _get_environ
from werkzeug._internal import _get_environ
from werkzeug.wrappers import BaseRequest
from werkzeug.urls import url_encode, url_fix, iri_to_uri, url_unquote, \
url_unparse, url_parse
Expand Down Expand Up @@ -596,7 +596,7 @@ def get_environ(self):
content_length = len(values)
input_stream = BytesIO(values)
else:
input_stream = _empty_stream
input_stream = BytesIO()

result = {}
if self.environ_base:
Expand Down
4 changes: 2 additions & 2 deletions werkzeug/wsgi.py
Expand Up @@ -27,7 +27,7 @@
from werkzeug._compat import BytesIO, PY2, implements_iterator, iteritems, \
make_literal_wrapper, string_types, text_type, to_bytes, to_unicode, \
try_coerce_native, wsgi_get_bytes
from werkzeug._internal import _empty_stream, _encode_idna
from werkzeug._internal import _encode_idna
from werkzeug.filesystem import get_filesystem_encoding
from werkzeug.http import http_date, is_resource_modified, \
is_hop_by_hop_header
Expand Down Expand Up @@ -226,7 +226,7 @@ def get_input_stream(environ, safe_fallback=True):
# potentially dangerous because it could be infinite, malicious or not. If
# safe_fallback is true, return an empty stream instead for safety.
if content_length is None:
return safe_fallback and _empty_stream or stream
return safe_fallback and BytesIO() or stream

# Otherwise limit the stream to the content length
return LimitedStream(stream, content_length)
Expand Down

0 comments on commit baf2051

Please sign in to comment.