Skip to content

Commit

Permalink
Add a test, and fix the C implementation, for farmatting a 64-bit oid.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Oct 20, 2018
1 parent 99c9462 commit 8e75681
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 10 deletions.
28 changes: 18 additions & 10 deletions persistent/cPersistence.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ static char cPersistence_doc_string[] =
"\n"
"$Id$\n";

#include <stdint.h>
#include "cPersistence.h"
#include "structmember.h"

Expand Down Expand Up @@ -1430,7 +1431,8 @@ Per_repr(cPersistentObject *self)
PyObject *result = NULL;

unsigned char* oid_bytes;
unsigned long long oid_value;
char buf[20];
uint64_t oid_value;

prepr = PyObject_GetAttrString((PyObject*)Py_TYPE(self), "_p_repr");
if (prepr)
Expand All @@ -1453,15 +1455,21 @@ Per_repr(cPersistentObject *self)

if (self->oid && PyBytes_Check(self->oid) && PyBytes_GET_SIZE(self->oid) == 8) {
oid_bytes = (unsigned char*)PyBytes_AS_STRING(self->oid);
oid_value = ((unsigned long long)oid_bytes[0] << 56)
| ((unsigned long long)oid_bytes[1] << 48)
| ((unsigned long long)oid_bytes[2] << 40)
| ((unsigned long long)oid_bytes[3] << 32)
| ((unsigned long long)oid_bytes[4] << 24)
| ((unsigned long long)oid_bytes[5] << 16)
| ((unsigned long long)oid_bytes[6] << 8)
| ((unsigned long long)oid_bytes[7]);
oid_str = PyUnicode_FromFormat(" oid 0x%x", oid_value);
oid_value = ((uint64_t)oid_bytes[0] << 56)
| ((uint64_t)oid_bytes[1] << 48)
| ((uint64_t)oid_bytes[2] << 40)
| ((uint64_t)oid_bytes[3] << 32)
| ((uint64_t)oid_bytes[4] << 24)
| ((uint64_t)oid_bytes[5] << 16)
| ((uint64_t)oid_bytes[6] << 8)
| ((uint64_t)oid_bytes[7]);
/*
Python's PyUnicode_FromFormat doesn't understand the ll
length modifier for %x, so to format a 64-bit value we need to
use stdio.
*/
snprintf(buf, sizeof(buf) - 1, "%llx", oid_value);
oid_str = PyUnicode_FromFormat(" oid 0x%s", buf);
}

if (!oid_str) {
Expand Down
15 changes: 15 additions & 0 deletions persistent/tests/test_persistence.py
Original file line number Diff line number Diff line change
Expand Up @@ -1740,6 +1740,21 @@ def test_repr_oid_no_jar(self):
result,
"<persistent.Persistent object at 0xdeadbeef oid " + self._HEX_OID + ">")

def test_64bit_oid(self):
import struct
p = self._makeOne()
oid_value = 2 << 62
self.assertEqual(oid_value.bit_length(), 64)
oid = struct.pack(">Q", oid_value)
self.assertEqual(oid, b'\x80\x00\x00\x00\x00\x00\x00\x00')

p._p_oid = oid
result = self._normalized_repr(p)
self.assertEqual(
result,
'<persistent.Persistent object at 0xdeadbeef oid 0x8000000000000000>'
)

def test_repr_no_oid_repr_jar_raises_exception(self):
p = self._makeOne()

Expand Down

0 comments on commit 8e75681

Please sign in to comment.