diff -r 9dbdb5e67103 Modules/_hashopenssl.c --- a/Modules/_hashopenssl.c Tue Aug 14 20:33:49 2012 +0200 +++ b/Modules/_hashopenssl.c Tue Aug 14 20:41:45 2012 +0200 @@ -66,31 +66,81 @@ } EVPobject; -static PyTypeObject EVPtype; +#define DEFINE_CONSTS_FOR_NEW(Name) \ + PyObject *CONST_ ## Name ## _name_obj; \ + EVP_MD_CTX CONST_new_ ## Name ## _ctx; \ + EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p; +typedef struct { + PyObject *EVPtype; + DEFINE_CONSTS_FOR_NEW(md5) + DEFINE_CONSTS_FOR_NEW(sha1) + #ifdef _OPENSSL_SUPPORTS_SHA2 + DEFINE_CONSTS_FOR_NEW(sha224) + DEFINE_CONSTS_FOR_NEW(sha256) + DEFINE_CONSTS_FOR_NEW(sha384) + DEFINE_CONSTS_FOR_NEW(sha512) + #endif +} _hashlibstate; -#define DEFINE_CONSTS_FOR_NEW(Name) \ - static PyObject *CONST_ ## Name ## _name_obj; \ - static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \ - static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL; +#define _hashlibstate(o) ((_hashlibstate *)PyModule_GetState(o)) -DEFINE_CONSTS_FOR_NEW(md5) -DEFINE_CONSTS_FOR_NEW(sha1) -#ifdef _OPENSSL_SUPPORTS_SHA2 -DEFINE_CONSTS_FOR_NEW(sha224) -DEFINE_CONSTS_FOR_NEW(sha256) -DEFINE_CONSTS_FOR_NEW(sha384) -DEFINE_CONSTS_FOR_NEW(sha512) -#endif +#define DEFINE_CONSTS_VISIT_FOR_NEW(Name) \ + Py_VISIT(_hashlibstate(m)->CONST_ ## Name ## _name_obj); +#define DEFINE_CONSTS_CLEAR_FOR_NEW(Name) \ + Py_CLEAR(_hashlibstate(m)->CONST_ ## Name ## _name_obj); + +static int +_hashlib_clear(PyObject *m) +{ + Py_CLEAR(_hashlibstate(m)->EVPtype); + DEFINE_CONSTS_CLEAR_FOR_NEW(md5) + DEFINE_CONSTS_CLEAR_FOR_NEW(sha1) + #ifdef _OPENSSL_SUPPORTS_SHA2 + DEFINE_CONSTS_CLEAR_FOR_NEW(sha224) + DEFINE_CONSTS_CLEAR_FOR_NEW(sha256) + DEFINE_CONSTS_CLEAR_FOR_NEW(sha384) + DEFINE_CONSTS_CLEAR_FOR_NEW(sha512) + #endif + return 0; +} + +static int +_hashlib_traverse(PyObject *m, visitproc visit, void *arg) +{ + Py_VISIT(_hashlibstate(m)->EVPtype); + DEFINE_CONSTS_VISIT_FOR_NEW(md5) + DEFINE_CONSTS_VISIT_FOR_NEW(sha1) + #ifdef _OPENSSL_SUPPORTS_SHA2 + DEFINE_CONSTS_VISIT_FOR_NEW(sha224) + DEFINE_CONSTS_VISIT_FOR_NEW(sha256) + DEFINE_CONSTS_VISIT_FOR_NEW(sha384) + DEFINE_CONSTS_VISIT_FOR_NEW(sha512) + #endif + return 0; +} + +static void +_hashlib_free(void *m) +{ + _hashlib_clear((PyObject *)m); +} + +static struct PyModuleDef _hashlibmodule; + +#define _hashlibstate_global \ + ((_hashlibstate *)PyModule_GetState(PyState_FindModule(&_hashlibmodule))) static EVPobject * newEVPobject(PyObject *name) { - EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, &EVPtype); + EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, + (PyTypeObject *)_hashlibstate_global->EVPtype); /* save the name for .name to return */ if (retval != NULL) { + Py_INCREF(_hashlibstate_global->EVPtype); Py_INCREF(name); retval->name = name; #ifdef WITH_THREAD @@ -122,6 +172,7 @@ static void EVP_dealloc(EVPobject *self) { + PyTypeObject *type = Py_TYPE(self); #ifdef WITH_THREAD if (self->lock != NULL) PyThread_free_lock(self->lock); @@ -129,6 +180,9 @@ EVP_MD_CTX_cleanup(&self->ctx); Py_XDECREF(self->name); PyObject_Del(self); + if((void *)type->tp_dealloc == (void *)EVP_dealloc) { + Py_DECREF(type); + } } static void locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self) @@ -367,50 +421,28 @@ name -- the hash algorithm being used by this object\n\ digest_size -- number of bytes in this hashes output\n"); -static PyTypeObject EVPtype = { - PyVarObject_HEAD_INIT(NULL, 0) - "_hashlib.HASH", /*tp_name*/ - sizeof(EVPobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)EVP_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - (reprfunc)EVP_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - hashtype_doc, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - EVP_methods, /* tp_methods */ - EVP_members, /* tp_members */ - EVP_getseters, /* tp_getset */ -#if 1 - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ +static PyType_Slot EVPtype_slots[] = { + {Py_tp_doc, hashtype_doc}, + {Py_tp_dealloc, EVP_dealloc}, + {Py_tp_repr, EVP_repr}, + {Py_tp_methods, EVP_methods}, + {Py_tp_members, EVP_members}, + {Py_tp_getset, EVP_getseters}, +#if HASH_OBJ_CONSTRUCTOR + {Py_tp_init, EVP_tp_init}, #endif -#if HASH_OBJ_CONSTRUCTOR - (initproc)EVP_tp_init, /* tp_init */ -#endif + {0, 0} }; +static PyType_Spec EVPtype_spec = { + "_hashlib.HASH", + sizeof(EVPobject), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + EVPtype_slots, +}; + + static PyObject * EVPnew(PyObject *name_obj, const EVP_MD *digest, const EVP_MD_CTX *initial_ctx, @@ -567,9 +599,9 @@ GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); \ \ ret_obj = EVPnew( \ - CONST_ ## NAME ## _name_obj, \ + _hashlibstate_global->CONST_ ## NAME ## _name_obj, \ NULL, \ - CONST_new_ ## NAME ## _ctx_p, \ + _hashlibstate_global->CONST_new_ ## NAME ## _ctx_p, \ (unsigned char*)view.buf, \ view.len); \ \ @@ -587,10 +619,10 @@ /* used in the init function to setup a constructor */ #define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \ - CONST_ ## NAME ## _name_obj = PyUnicode_FromString(#NAME); \ + _hashlibstate(m)->CONST_ ## NAME ## _name_obj = PyUnicode_FromString(#NAME); \ if (EVP_get_digestbyname(#NAME)) { \ - CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \ - EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \ + _hashlibstate(m)->CONST_new_ ## NAME ## _ctx_p = &_hashlibstate(m)->CONST_new_ ## NAME ## _ctx; \ + EVP_DigestInit(_hashlibstate(m)->CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \ } \ } while (0); @@ -626,12 +658,12 @@ PyModuleDef_HEAD_INIT, "_hashlib", NULL, - -1, + sizeof(_hashlibstate), EVP_functions, NULL, - NULL, - NULL, - NULL + _hashlib_traverse, + _hashlib_clear, + _hashlib_free }; PyMODINIT_FUNC @@ -639,19 +671,23 @@ { PyObject *m, *openssl_md_meth_names; + m = PyState_FindModule(&_hashlibmodule); + if(!m){ + m = PyModule_Create(&_hashlibmodule); + if (m == NULL) + return NULL; + } else { + Py_INCREF(m); + return m; + } OpenSSL_add_all_digests(); /* TODO build EVP_functions openssl_* entries dynamically based * on what hashes are supported rather than listing many * but having some be unsupported. Only init appropriate * constants. */ - - Py_TYPE(&EVPtype) = &PyType_Type; - if (PyType_Ready(&EVPtype) < 0) - return NULL; - - m = PyModule_Create(&_hashlibmodule); - if (m == NULL) + _hashlibstate(m)->EVPtype = PyType_FromSpec(&EVPtype_spec); + if (_hashlibstate(m)->EVPtype == NULL) return NULL; openssl_md_meth_names = generate_hash_name_list(); @@ -665,8 +701,8 @@ } #if HASH_OBJ_CONSTRUCTOR - Py_INCREF(&EVPtype); - PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype); + Py_INCREF(_hashlibstate(m)->EVPtype); + PyModule_AddObject(m, "HASH", _hashlibstate(m)->EVPtype); #endif /* these constants are used by the convenience constructors */