Mon Mar  2 20:30:25 MST 2009  zooko@zooko.com
  * allow sha256 .update() after .digest()
  Also switch the way casting of the de-allocator is done to narrow the scope of what gets cast.
  This patch comes with a unit test, which it fails, showing that there is a bug in it.

New patches:

[allow sha256 .update() after .digest()
zooko@zooko.com**20090303033025
 Ignore-this: 57c079abc00e8ee8a51e40fc773789e6
 Also switch the way casting of the de-allocator is done to narrow the scope of what gets cast.
 This patch comes with a unit test, which it fails, showing that there is a bug in it.
] {
hunk ./pycryptopp/hash/sha256module.cpp 27
 
     /* internal */
     CryptoPP::SHA256* h;
-    PyStringObject* digest;
 } SHA256;
 
 PyDoc_STRVAR(SHA256__doc__,
hunk ./pycryptopp/hash/sha256module.cpp 36
 
 static PyObject *
 SHA256_update(SHA256* self, PyObject* msgobj) {
-    if (self->digest)
-        return PyErr_Format(sha256_error, "Precondition violation: once .digest() has been called you are required to never call .update() again.");
-
     const char *msg;
     Py_ssize_t msgsize;
     if (PyString_AsStringAndSize(msgobj, const_cast<char**>(&msg), &msgsize))
hunk ./pycryptopp/hash/sha256module.cpp 50
 
 static PyObject *
 SHA256_digest(SHA256* self, PyObject* dummy) {
-    if (!self->digest) {
-        self->digest = reinterpret_cast<PyStringObject*>(PyString_FromStringAndSize(NULL, self->h->DigestSize()));
-        if (!self->digest)
-            return NULL;
-        self->h->Final(reinterpret_cast<byte*>(PyString_AS_STRING(self->digest)));
-    }
+    // TODO: detect digest-size at compile time not runtime
+    PyStringObject* result = reinterpret_cast<PyStringObject*>(PyString_FromStringAndSize(NULL, self->h->DigestSize()));
+    if (!result)
+        return NULL;
+
+    self->h->Final(reinterpret_cast<byte*>(PyString_AS_STRING(result)));
 
hunk ./pycryptopp/hash/sha256module.cpp 57
-    Py_INCREF(self->digest);
-    return reinterpret_cast<PyObject*>(self->digest);
+    return reinterpret_cast<PyObject*>(result);
 }
 
 PyDoc_STRVAR(SHA256_digest__doc__,
hunk ./pycryptopp/hash/sha256module.cpp 99
     self->h = new CryptoPP::SHA256();
     if (!self->h)
         return PyErr_NoMemory();
-    self->digest = NULL;
     return reinterpret_cast<PyObject*>(self);
 }
 
hunk ./pycryptopp/hash/sha256module.cpp 103
 static void
-SHA256_dealloc(SHA256* self) {
-    Py_XDECREF(self->digest);
-    delete self->h;
-    self->ob_type->tp_free((PyObject*)self);
+SHA256_dealloc(PyObject* self) {
+    SHA256* typedself = reinterpret_cast<SHA256*>(self);
+    delete typedself->h;
+    typedself->ob_type->tp_free(self);
 }
 
 static int
hunk ./pycryptopp/hash/sha256module.cpp 128
     "sha256.SHA256", /*tp_name*/
     sizeof(SHA256),             /*tp_basicsize*/
     0,                         /*tp_itemsize*/
-    reinterpret_cast<destructor>(SHA256_dealloc), /*tp_dealloc*/
+    SHA256_dealloc, /*tp_dealloc*/
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
hunk ./pycryptopp/hash/sha256module.cpp 159
     0,                         /* tp_descr_get */
     0,                         /* tp_descr_set */
     0,                         /* tp_dictoffset */
-    //reinterpret_cast<initproc>(SHA256_init),               /* tp_init */
     SHA256_init,               /* tp_init */
     0,                         /* tp_alloc */
     SHA256_new,                /* tp_new */
hunk ./pycryptopp/test/test_sha256.py 67
 
     def test_constructor_type_check(self):
         self.failUnlessRaises(TypeError, sha256.SHA256, None)
-                              
+
     def test_update_type_check(self):
         h = sha256.SHA256()
         self.failUnlessRaises(TypeError, h.update, None)
hunk ./pycryptopp/test/test_sha256.py 79
         d2 = h.digest()
         self.failUnlessEqual(d1, d2)
 
-    def test_digest_then_update_fail(self):
+    def test_digest_then_update(self):
         h = sha256.SHA256()
         d1 = h.digest()
hunk ./pycryptopp/test/test_sha256.py 82
-        try:
-            h.update("oops")
-        except sha256.Error, le:
-            self.failUnless("digest() has been called" in str(le), le)
+        h.update("MORE")
+        d2 = h.digest()
+        self.failIfEqual(d1, d2)
+
+        h2 = sha256.SHA256()
+        h2.update("MORE")
+        d3 = h2.digest()
+
+        self.failUnlessEqual(d2, d3)
+
+        h = sha256.SHA256()
+        h.update("abcde")
+        d4 = h.digest()
+        h.update("fghij")
+        d5 = h.digest()
+        self.failIfEqual(d4, d5)
+
+        h = sha256.SHA256()
+        h.update("abcdefghij")
+        d6 = h.digest()
+        self.failUnlessEqual(d5, d6)
+    test_digest_then_update.todo = "todo: make this work"
+
 
 VECTS_RE=re.compile("\nLen = ([0-9]+)\nMsg = ([0-9a-f]+)\nMD = ([0-9a-f]+)")
 
}

Context:

[TAG pycryptopp-0.5.12
zooko@zooko.com**20081119210020
 Ignore-this: 73b90e9bd66f02ef953e441fae9d5917
] 
Patch bundle hash:
a0e80c20740840f50be8acf6999bdb4e4fee408a
