Skip to content

Commit

Permalink
Make sure buffer size is more than 0
Browse files Browse the repository at this point in the history
This is an attempt to fix a data corruption issue, that manifests in a
random byte replacing a correct one in a pickle.
  • Loading branch information
kedder committed Jun 10, 2019
1 parent aa2f39a commit 9b300ef
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
1.0.4 (unreleased)
==================

- Nothing changed yet.
- Fix pickle corruption under certain conditions. See `pull request 47
https://github.com/zopefoundation/zodbpickle/pull/47`_.


1.0.3 (2018-12-18)
Expand Down
2 changes: 1 addition & 1 deletion src/zodbpickle/_pickle_33.c
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ _Pickler_Write(PicklerObject *self, const char *s, Py_ssize_t n)
PyErr_NoMemory();
return -1;
}
self->max_output_len = (self->output_len + n) / 2 * 3;
self->max_output_len = (self->output_len + n) / 2 * 3 + 1;
if (_PyBytes_Resize(&self->output_buffer, self->max_output_len) < 0)
return -1;
}
Expand Down
23 changes: 23 additions & 0 deletions src/zodbpickle/tests/pickletester_3.py
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,29 @@ def test_setitems_on_non_dicts(self):
else:
self._check_pickling_with_opcode(obj, pickle.SETITEMS, proto)

def test_corrupted_pickle(self):
# Former C implementation produced corrupted pickles on these samples.
# See https://github.com/zopefoundation/zodbpickle/pull/47
sample1 = ['a'] * 17509
dumped = self.dumps(sample1, 0)
loaded = self.loads(dumped)
self.assertEqual(loaded, sample1)

sample2 = ['a'] * 34992
dumped = self.dumps(sample2, 1)
loaded = self.loads(dumped)
self.assertEqual(loaded, sample2)

sample3 = ['a'] * 34991
dumped = self.dumps(sample3, 2)
loaded = self.loads(dumped)
self.assertEqual(loaded, sample3)

sample4 = ['a'] * 34991
dumped = self.dumps(sample4, 3)
loaded = self.loads(dumped)
self.assertEqual(loaded, sample4)


class AbstractBytestrTests(unittest.TestCase):
def unpickleEqual(self, data, unpickled):
Expand Down

0 comments on commit 9b300ef

Please sign in to comment.