Fixing another edge case in the \r\n handling

Increasing version to 0.9
This commit is contained in:
Charles Gordon
2013-02-08 18:02:04 -08:00
parent 6f1cc2a470
commit f05fbe37da
3 changed files with 59 additions and 11 deletions

View File

@@ -751,18 +751,20 @@ def _readline(sock, buf):
last_char = '' last_char = ''
while True: while True:
idx = buf.find('\r\n')
# We're reading in chunks, so "\r\n" could appear in one chunk, # We're reading in chunks, so "\r\n" could appear in one chunk,
# or across the boundary of two chunks, so we check for both # or across the boundary of two chunks, so we check for both
# cases. # cases.
if idx != -1:
before, sep, after = buf.partition("\r\n") # This case must appear first, since the buffer could have
chunks.append(before) # later \r\n characters in it and we want to get the first \r\n.
return after, ''.join(chunks) if last_char == '\r' and buf[0] == '\n':
elif last_char == '\r' and buf[0] == '\n':
# Strip the last character from the last chunk. # Strip the last character from the last chunk.
chunks[-1] = chunks[-1][:-1] chunks[-1] = chunks[-1][:-1]
return buf[1:], ''.join(chunks) return buf[1:], ''.join(chunks)
elif buf.find('\r\n') != -1:
before, sep, after = buf.partition("\r\n")
chunks.append(before)
return after, ''.join(chunks)
if buf: if buf:
chunks.append(buf) chunks.append(buf)

View File

@@ -237,12 +237,58 @@ def test_get_many_all_found():
tools.assert_equal(result, {'key1': 'value1', 'key2': 'value2'}) tools.assert_equal(result, {'key1': 'value1', 'key2': 'value2'})
def test_get_many_cr_nl_boundary_issue(): def test_cr_nl_boundaries():
client = Client(None) client = Client(None)
client.sock = MockSocket(['VALUE key1 0 6\r', '\nvalue1\r', '\n', client.sock = MockSocket(['VALUE key1 0 6\r',
'VALUE key2 0 6\r', '\nvalue2', '\r\nEND\r\n']) '\nvalue1\r\n'
'VALUE key2 0 6\r\n',
'value2\r\n'
'END\r\n'])
result = client.get_many(['key1', 'key2']) result = client.get_many(['key1', 'key2'])
tools.assert_equal(result, {'key1': 'value1', 'key2': 'value2'}) tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'})
client.sock = MockSocket(['VALUE key1 0 6\r\n',
'value1\r',
'\nVALUE key2 0 6\r\n',
'value2\r\n',
'END\r\n'])
result = client.get_many(['key1', 'key2'])
tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'})
client.sock = MockSocket(['VALUE key1 0 6\r\n',
'value1\r\n',
'VALUE key2 0 6\r',
'\nvalue2\r\n',
'END\r\n'])
result = client.get_many(['key1', 'key2'])
tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'})
client.sock = MockSocket(['VALUE key1 0 6\r\n',
'value1\r\n',
'VALUE key2 0 6\r\n',
'value2\r',
'\nEND\r\n'])
result = client.get_many(['key1', 'key2'])
tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'})
client.sock = MockSocket(['VALUE key1 0 6\r\n',
'value1\r\n',
'VALUE key2 0 6\r\n',
'value2\r\n',
'END\r',
'\n'])
result = client.get_many(['key1', 'key2'])
tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'})
client.sock = MockSocket(['VALUE key1 0 6\r',
'\nvalue1\r',
'\nVALUE key2 0 6\r',
'\nvalue2\r',
'\nEND\r',
'\n'])
result = client.get_many(['key1', 'key2'])
tools.assert_equals(result, {'key1': 'value1', 'key2': 'value2'})
def test_get_unknown_error(): def test_get_unknown_error():

View File

@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
setup( setup(
name = 'pymemcache', name = 'pymemcache',
version = '0.8', version = '0.9',
author = 'Charles Gordon', author = 'Charles Gordon',
author_email = 'charles@pinterest.com', author_email = 'charles@pinterest.com',
packages = find_packages(), packages = find_packages(),