Commit cac3d5bf authored by Florent Guillaume's avatar Florent Guillaume

Collector #1498: Don't choke on malformed cookies. Cookies of the form

"foo=bar; hmm; baz=gee" will give an empty value for 'hmm' instead of
silently discarding it and the rest of the string. (Thanks to 'sirilyan'
for the patch.)
parent 066b9e9e
...@@ -46,6 +46,11 @@ Zope Changes ...@@ -46,6 +46,11 @@ Zope Changes
Bugs fixed Bugs fixed
- Collector #1498: Don't choke on malformed cookies. Cookies of
the form "foo=bar; hmm; baz=gee" will give an empty value for
'hmm' instead of silently discarding it and the rest of the
string. (Thanks to 'sirilyan' for the patch.)
- bin/zopectl test now uses os.execv, instead os os.system, - bin/zopectl test now uses os.execv, instead os os.system,
so that options with characters that needs shell quoting so that options with characters that needs shell quoting
doesn't break the command. doesn't break the command.
......
...@@ -29,6 +29,8 @@ from cgi import escape ...@@ -29,6 +29,8 @@ from cgi import escape
CopyError='Copy Error' CopyError='Copy Error'
copy_re = re.compile('^copy([0-9]*)_of_(.*)')
_marker=[] _marker=[]
class CopyContainer(ExtensionClass.Base): class CopyContainer(ExtensionClass.Base):
"""Interface for containerish objects which allow cut/copy/paste""" """Interface for containerish objects which allow cut/copy/paste"""
...@@ -113,19 +115,17 @@ class CopyContainer(ExtensionClass.Base): ...@@ -113,19 +115,17 @@ class CopyContainer(ExtensionClass.Base):
return self.manage_main(self, REQUEST) return self.manage_main(self, REQUEST)
return cp return cp
copy_re=re.compile('^copy[0-9]*_of_')
def _get_id(self, id): def _get_id(self, id):
# Allow containers to override the generation of # Allow containers to override the generation of
# object copy id by attempting to call its _get_id # object copy id by attempting to call its _get_id
# method, if it exists. # method, if it exists.
copy_match=self.copy_re.match(id) match = copy_re.match(id)
if (copy_match) and (copy_match.end() < len(id)): if match:
n=1 n = int(match.group(1) or '1')
orig_id=self.copy_re.sub('', id) orig_id = match.group(2)
else: else:
n=0 n = 0
orig_id=id orig_id = id
while 1: while 1:
if self._getOb(id, None) is None: if self._getOb(id, None) is None:
return id return id
......
...@@ -183,6 +183,43 @@ class TestCopySupport( CopySupportTestBase ): ...@@ -183,6 +183,43 @@ class TestCopySupport( CopySupportTestBase ):
self.failUnless( 'copy_of_file' in self.folder2.objectIds() ) self.failUnless( 'copy_of_file' in self.folder2.objectIds() )
self.failUnless( result == [{'id':'file', 'new_id':'copy_of_file'}]) self.failUnless( result == [{'id':'file', 'new_id':'copy_of_file'}])
def testPasteSingleSameIDMultipleTimes(self):
cookie = self.folder1.manage_copyObjects(ids=('file',))
result = self.folder1.manage_pasteObjects(cookie)
self.assertEqual(self.folder1.objectIds(), ['file', 'copy_of_file'])
self.assertEqual(result, [{'id':'file', 'new_id':'copy_of_file'}])
# make another copy of file
cookie = self.folder1.manage_copyObjects(ids=('file',))
result = self.folder1.manage_pasteObjects(cookie)
self.assertEqual(self.folder1.objectIds(),
['file', 'copy_of_file', 'copy2_of_file'])
self.assertEqual(result, [{'id':'file', 'new_id':'copy2_of_file'}])
# now copy the copy
cookie = self.folder1.manage_copyObjects(ids=('copy_of_file',))
result = self.folder1.manage_pasteObjects(cookie)
self.assertEqual(self.folder1.objectIds(),
['file', 'copy_of_file', 'copy2_of_file',
'copy3_of_file'])
self.assertEqual(result, [{'id':'copy_of_file',
'new_id':'copy3_of_file'}])
# or copy another copy
cookie = self.folder1.manage_copyObjects(ids=('copy2_of_file',))
result = self.folder1.manage_pasteObjects(cookie)
self.assertEqual(self.folder1.objectIds(),
['file', 'copy_of_file', 'copy2_of_file',
'copy3_of_file', 'copy4_of_file'])
self.assertEqual(result, [{'id':'copy2_of_file',
'new_id':'copy4_of_file'}])
def testPasteSpecialName(self):
manage_addFile(self.folder1, 'copy_of_',
file='', content_type='text/plain')
cookie = self.folder1.manage_copyObjects(ids=('copy_of_',))
result = self.folder1.manage_pasteObjects(cookie)
self.assertEqual(self.folder1.objectIds(),
['file', 'copy_of_', 'copy2_of_'])
self.assertEqual(result, [{'id':'copy_of_', 'new_id':'copy2_of_'}])
def testPasteMultiNotSameID( self ): def testPasteMultiNotSameID( self ):
self.failUnless( 'file' in self.folder1.objectIds() ) self.failUnless( 'file' in self.folder1.objectIds() )
self.failIf( 'file1' in self.folder1.objectIds() ) self.failIf( 'file1' in self.folder1.objectIds() )
......
...@@ -1438,6 +1438,8 @@ def parse_cookie(text, ...@@ -1438,6 +1438,8 @@ def parse_cookie(text,
'([\x00- ]*([^\x00- ;,="]+)="([^"]*)"([\x00- ]*[;,])?[\x00- ]*)'), '([\x00- ]*([^\x00- ;,="]+)="([^"]*)"([\x00- ]*[;,])?[\x00- ]*)'),
parmre=re.compile( parmre=re.compile(
'([\x00- ]*([^\x00- ;,="]+)=([^\x00- ;,"]*)([\x00- ]*[;,])?[\x00- ]*)'), '([\x00- ]*([^\x00- ;,="]+)=([^\x00- ;,"]*)([\x00- ]*[;,])?[\x00- ]*)'),
paramlessre=re.compile(
'([\x00- ]*([^\x00- ;,="]+)[\x00- ]*[;,][\x00- ]*)'),
acquire=parse_cookie_lock.acquire, acquire=parse_cookie_lock.acquire,
release=parse_cookie_lock.release, release=parse_cookie_lock.release,
...@@ -1468,6 +1470,14 @@ def parse_cookie(text, ...@@ -1468,6 +1470,14 @@ def parse_cookie(text,
name = mo_p.group(2) name = mo_p.group(2)
value = mo_p.group(3) value = mo_p.group(3)
else:
# Broken Cookie without = nor value.
broken_p = paramlessre.match(text)
if broken_p:
l = len(broken_p.group(1))
name = broken_p.group(2)
value = ''
else: else:
return result return result
......
...@@ -564,6 +564,25 @@ class ProcessInputsTests(unittest.TestCase): ...@@ -564,6 +564,25 @@ class ProcessInputsTests(unittest.TestCase):
self._noTaintedValues(req) self._noTaintedValues(req)
self._onlyTaintedformHoldsTaintedStrings(req) self._onlyTaintedformHoldsTaintedStrings(req)
def testCookieParsing(self):
env = {'SERVER_NAME': 'testingharnas', 'SERVER_PORT': '80'}
env['HTTP_COOKIE'] = 'foo=bar; baz=gee'
req = self._getHTTPRequest(env)
self.assertEquals(req.cookies['foo'], 'bar')
self.assertEquals(req.cookies['baz'], 'gee')
env['HTTP_COOKIE'] = 'foo=bar; baz="gee, like, e=mc^2"'
req = self._getHTTPRequest(env)
self.assertEquals(req.cookies['foo'], 'bar')
self.assertEquals(req.cookies['baz'], 'gee, like, e=mc^2')
# Collector #1498: empty cookies
env['HTTP_COOKIE'] = 'foo=bar; hmm; baz=gee'
req = self._getHTTPRequest(env)
self.assertEquals(req.cookies['foo'], 'bar')
self.assertEquals(req.cookies['hmm'], '')
self.assertEquals(req.cookies['baz'], 'gee')
TEST_ENVIRON = { TEST_ENVIRON = {
'CONTENT_TYPE': 'multipart/form-data; boundary=12345', 'CONTENT_TYPE': 'multipart/form-data; boundary=12345',
......
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