Commit 207f492d authored by Shane Hathaway's avatar Shane Hathaway

Fixed two leaks involving file uploads. The HTTP input stream was

referenced for too long.
parent 21fc4cb4
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
############################################################################## ##############################################################################
__version__='$Revision: 1.89 $'[11:-2] __version__='$Revision: 1.90 $'[11:-2]
import re, sys, os, urllib, time, random, cgi, codecs import re, sys, os, urllib, time, random, cgi, codecs
from types import StringType, UnicodeType from types import StringType, UnicodeType
...@@ -130,6 +130,11 @@ class HTTPRequest(BaseRequest): ...@@ -130,6 +130,11 @@ class HTTPRequest(BaseRequest):
return r return r
def close(self): def close(self):
# Clear all references to the input stream, possibly
# removing tempfiles.
self.stdin = None
self._file = None
self.form.clear()
# we want to clear the lazy dict here because BaseRequests don't have # we want to clear the lazy dict here because BaseRequests don't have
# one. Without this, there's the possibility of memory leaking # one. Without this, there's the possibility of memory leaking
# after every request. # after every request.
......
...@@ -565,11 +565,48 @@ class ProcessInputsTests(unittest.TestCase): ...@@ -565,11 +565,48 @@ class ProcessInputsTests(unittest.TestCase):
self._onlyTaintedformHoldsTaintedStrings(req) self._onlyTaintedformHoldsTaintedStrings(req)
TEST_ENVIRON = {
'CONTENT_TYPE': 'multipart/form-data; boundary=12345',
'REQUEST_METHOD': 'POST',
'SERVER_NAME': 'localhost',
'SERVER_PORT': '80',
}
TEST_FILE_DATA = '''
--12345
Content-Disposition: form-data; name="file"; filename="file"
Content-Type: application/octet-stream
test
--12345--
'''
class RequestTests( unittest.TestCase ):
def testRemoveStdinReferences(self):
# Verifies that all references to the input stream go away on
# request.close(). Otherwise a tempfile may stick around.
import sys
from StringIO import StringIO
s = StringIO(TEST_FILE_DATA)
env = TEST_ENVIRON.copy()
start_count = sys.getrefcount(s)
from ZPublisher.HTTPRequest import HTTPRequest
req = HTTPRequest(s, env, None)
req.processInputs()
self.assertNotEqual(start_count, sys.getrefcount(s)) # Precondition
req.close()
self.assertEqual(start_count, sys.getrefcount(s)) # The test
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(RecordTests, 'test')) suite.addTest(unittest.makeSuite(RecordTests, 'test'))
suite.addTest(unittest.makeSuite(ProcessInputsTests, 'test')) suite.addTest(unittest.makeSuite(ProcessInputsTests, 'test'))
suite.addTest(unittest.makeSuite(RequestTests, 'test'))
return suite return suite
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main(defaultTest='test_suite')
...@@ -333,7 +333,8 @@ class zhttp_channel(http_channel): ...@@ -333,7 +333,8 @@ class zhttp_channel(http_channel):
while self.queue: while self.queue:
self.queue.pop() self.queue.pop()
if self.current_request is not None: if self.current_request is not None:
self.current_request.channel=None # break circ refs self.current_request.collector = None # break circ refs
self.current_request.channel = None # break circ refs
self.current_request=None self.current_request=None
while self.producer_fifo: while self.producer_fifo:
p=self.producer_fifo.first() p=self.producer_fifo.first()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment