Skip to content

Commit fadb7c9

Browse files
authored
Merge pull request #64 from mehcode/fix_memory_leaks
Fix memory leaks #63
2 parents ae9c5da + 20321f2 commit fadb7c9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+815
-616
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ install:
2323
- travis_retry pip install -r requirements-test.txt
2424
- travis_retry pip install -e "."
2525
- pip list
26-
script: py.test tests
26+
script: py.test -v tests
2727

2828
before_deploy:
2929
- travis_retry pip install Sphinx

README.rst

+4-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Python bindings for the XML Security Library.
1515
Usage
1616
******
1717

18-
Check the `examples <https://github.com/mehcode/python-xmlsec/tree/master/tests/examples>`_ to see various examples of signing and verifying using the library.
18+
Check the `examples <http://pythonhosted.org/xmlsec/examples>`_ to see various examples of signing and verifying using the library.
1919

2020
************
2121
Requirements
@@ -146,6 +146,9 @@ Running the test suite
146146
147147
py.test tests
148148
149+
3. Tests configuration
150+
Env variable **PYXMLSEC_TEST_ITERATIONS** specifies number of test iterations to detect memory leaks.
151+
149152
Reporting a issue
150153
-----------------
151154
Please attach the output of following information:

doc/source/modules/constants.rst

+5
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,21 @@ Nodes
7474
- *NodeObject* - Object
7575
- *NodeManifest* - Manifest
7676
- *NodeEncryptedData* - EncryptedData
77+
- *NodeEncryptedKey* - EncryptedKey
7778
- *NodeEncryptionMethod* - EncryptionMethod
7879
- *NodeEncryptionProperties* - EncryptionProperties
7980
- *NodeEncryptionProperty* - EncryptionProperty
8081
- *NodeCipherData* - CipherData
8182
- *NodeCipherValue* - CipherValue
8283
- *NodeCipherReference* - CipherReference
84+
- *NodeReference - Reference
8385
- *NodeReferenceList* - ReferenceList
8486
- *NodeDataReference* - DataReference
8587
- *NodeKeyReference* - KeyReference
8688
- *NodeKeyInfo* - KeyInfo
89+
- *NodeKeyName - KeyName
90+
- *NodeKeyValue - KeyValue
91+
- *NodeX509Data - X509Data
8792
8893
Transforms
8994
**********

src/constants.c

+5
Original file line numberDiff line numberDiff line change
@@ -348,9 +348,14 @@ int PyXmlSec_ConstantsModule_Init(PyObject* package) {
348348
PYXMLSEC_ADD_NODE_CONSTANT(NodeDataReference, "DATA_REFERENCE");
349349
PYXMLSEC_ADD_NODE_CONSTANT(NodeKeyReference, "KEY_REFERENCE");
350350

351+
PYXMLSEC_ADD_NODE_CONSTANT(NodeReference, "REFERENCE");
351352
PYXMLSEC_ADD_NODE_CONSTANT(NodeReferenceList, "REFERENCE_LIST");
352353

353354
PYXMLSEC_ADD_NODE_CONSTANT(NodeKeyInfo, "KEY_INFO");
355+
PYXMLSEC_ADD_NODE_CONSTANT(NodeKeyName, "KEY_NAME");
356+
PYXMLSEC_ADD_NODE_CONSTANT(NodeKeyValue, "KEY_VALUE");
357+
358+
PYXMLSEC_ADD_NODE_CONSTANT(NodeX509Data, "X509_DATA");
354359

355360
PYXMLSEC_CLOSE_NAMESPACE(nodeCls);
356361
#undef PYXMLSEC_ADD_NODE_CONSTANT

src/ds.c

+13-5
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,20 @@ static int PyXmlSec_SignatureContext__init__(PyObject* self, PyObject* args, PyO
3939
PYXMLSEC_DEBUGF("%p: init sign context", self);
4040
PyXmlSec_SignatureContext* ctx = (PyXmlSec_SignatureContext*)self;
4141
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:__init__", kwlist, PyXmlSec_KeysManagerConvert, &manager)) {
42-
return -1;
42+
goto ON_FAIL;
4343
}
44-
PYXMLSEC_DEBUGF("%p", manager);
4544
ctx->handle = xmlSecDSigCtxCreate(manager != NULL ? manager->handle : NULL);
4645
if (ctx->handle == NULL) {
4746
PyXmlSec_SetLastError("failed to create the digital signature context");
48-
return -1;
47+
goto ON_FAIL;
4948
}
50-
Py_XINCREF(manager);
5149
ctx->manager = manager;
50+
PYXMLSEC_DEBUGF("%p: init sign context - ok, manager - %p", self, manager);
5251
return 0;
52+
ON_FAIL:
53+
PYXMLSEC_DEBUGF("%p: init sign context - failed", self);
54+
Py_XDECREF(manager);
55+
return -1;
5356
}
5457

5558
static void PyXmlSec_SignatureContext__del__(PyObject* self) {
@@ -65,8 +68,13 @@ static void PyXmlSec_SignatureContext__del__(PyObject* self) {
6568

6669
static const char PyXmlSec_SignatureContextKey__doc__[] = "Signature key.\n";
6770
static PyObject* PyXmlSec_SignatureContextKeyGet(PyObject* self, void* closure) {
71+
PyXmlSec_SignatureContext* ctx = ((PyXmlSec_SignatureContext*)self);
72+
if (ctx->handle->signKey == NULL) {
73+
Py_RETURN_NONE;
74+
}
75+
6876
PyXmlSec_Key* key = PyXmlSec_NewKey();
69-
key->handle = ((PyXmlSec_SignatureContext*)self)->handle->signKey;
77+
key->handle = ctx->handle->signKey;
7078
key->is_own = 0;
7179
return (PyObject*)key;
7280
}

src/enc.c

+22-14
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ typedef struct {
2424

2525
static PyObject* PyXmlSec_EncryptionContext__new__(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
2626
PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)PyType_GenericNew(type, args, kwargs);
27-
PYXMLSEC_DEBUGF("%p: new sign context", ctx);
27+
PYXMLSEC_DEBUGF("%p: new enc context", ctx);
2828
if (ctx != NULL) {
2929
ctx->handle = NULL;
3030
ctx->manager = NULL;
@@ -37,24 +37,26 @@ static int PyXmlSec_EncryptionContext__init__(PyObject* self, PyObject* args, Py
3737

3838
PyXmlSec_KeysManager* manager = NULL;
3939
PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self;
40-
PYXMLSEC_DEBUGF("%p: init sign context", self);
40+
PYXMLSEC_DEBUGF("%p: init enc context", self);
4141
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:__init__", kwlist, PyXmlSec_KeysManagerConvert, &manager)) {
42-
return -1;
42+
goto ON_FAIL;
4343
}
44-
45-
PYXMLSEC_DEBUGF("%p", manager);
4644
ctx->handle = xmlSecEncCtxCreate(manager != NULL ? manager->handle : NULL);
4745
if (ctx->handle == NULL) {
48-
PyXmlSec_SetLastError("failed to create the digital signature context");
49-
return -1;
46+
PyXmlSec_SetLastError("failed to create the encryption context");
47+
goto ON_FAIL;
5048
}
51-
Py_XINCREF(manager);
5249
ctx->manager = manager;
50+
PYXMLSEC_DEBUGF("%p: init enc context - ok, manager - %p", self, manager);
5351
return 0;
52+
ON_FAIL:
53+
PYXMLSEC_DEBUGF("%p: init enc context - failed", self);
54+
Py_XDECREF(manager);
55+
return -1;
5456
}
5557

5658
static void PyXmlSec_EncryptionContext__del__(PyObject* self) {
57-
PYXMLSEC_DEBUGF("%p: delete sign context", self);
59+
PYXMLSEC_DEBUGF("%p: delete enc context", self);
5860
PyXmlSec_EncryptionContext* ctx = (PyXmlSec_EncryptionContext*)self;
5961
if (ctx->handle != NULL) {
6062
xmlSecEncCtxDestroy(ctx->handle);
@@ -66,8 +68,13 @@ static void PyXmlSec_EncryptionContext__del__(PyObject* self) {
6668

6769
static const char PyXmlSec_EncryptionContextKey__doc__[] = "Encryption key.\n";
6870
static PyObject* PyXmlSec_EncryptionContextKeyGet(PyObject* self, void* closure) {
71+
PyXmlSec_EncryptionContext* ctx = ((PyXmlSec_EncryptionContext*)self);
72+
if (ctx->handle->encKey == NULL) {
73+
Py_RETURN_NONE;
74+
}
75+
6976
PyXmlSec_Key* key = PyXmlSec_NewKey();
70-
key->handle = ((PyXmlSec_EncryptionContext*)self)->handle->encKey;
77+
key->handle = ctx->handle->encKey;
7178
key->is_own = 0;
7279
return (PyObject*)key;
7380
}
@@ -142,9 +149,10 @@ static void PyXmlSec_ClearReplacedNodes(xmlSecEncCtxPtr ctx, PyXmlSec_LxmlDocume
142149
xmlNodePtr n = ctx->replacedNodeList;
143150
xmlNodePtr nn;
144151
while (n != NULL) {
152+
PYXMLSEC_DEBUGF("clear replaced node %p", n);
145153
nn = n->next;
146154
// if n has references, it will not be deleted
147-
Py_XDECREF(PyXmlSec_elementFactory(doc, n));
155+
Py_DECREF(PyXmlSec_elementFactory(doc, n));
148156
n = nn;
149157
}
150158
ctx->replacedNodeList = NULL;
@@ -290,7 +298,7 @@ static PyObject* PyXmlSec_EncryptionContextDecrypt(PyObject* self, PyObject* arg
290298
}
291299

292300
xmlNodePtr xparent = node->_c_node->parent;
293-
if (xparent != NULL && !_isElement(xparent)) {
301+
if (xparent != NULL && !PyXmlSec_IsElement(xparent)) {
294302
xparent = NULL;
295303
}
296304

@@ -323,7 +331,7 @@ static PyObject* PyXmlSec_EncryptionContextDecrypt(PyObject* self, PyObject* arg
323331
if (!ctx->resultReplaced) {
324332
Py_XDECREF(node_num);
325333
Py_XDECREF(parent);
326-
PYXMLSEC_DEBUGF("%p: decrypt - ok", self);
334+
PYXMLSEC_DEBUGF("%p: binary.decrypt - ok", self);
327335
return PyBytes_FromStringAndSize(
328336
(const char*)xmlSecBufferGetData(ctx->result), (Py_ssize_t)xmlSecBufferGetSize(ctx->result)
329337
);
@@ -341,7 +349,7 @@ static PyObject* PyXmlSec_EncryptionContextDecrypt(PyObject* self, PyObject* arg
341349
parent = tmp;
342350
}
343351
Py_DECREF(node_num);
344-
PYXMLSEC_DEBUGF("%p: decrypt - ok", self);
352+
PYXMLSEC_DEBUGF("%p: parent.decrypt - ok", self);
345353
return parent;
346354
}
347355

src/exception.c

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ void PyXmlSec_SetLastError2(PyObject* type, const char* msg) {
122122
}
123123
}
124124
PyErr_SetObject(type, last);
125+
Py_DECREF(last);
125126
}
126127

127128
void PyXmlSec_SetLastError(const char* msg) {

src/keys.c

+14-4
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,11 @@ static PyObject* PyXmlSec_KeyNameGet(PyObject* self, void* closure) {
354354
PyErr_SetString(PyExc_ValueError, "key is not ready");
355355
return NULL;
356356
}
357-
return PyString_FromString((const char*)xmlSecKeyGetName(handle));
357+
const char* cname = (const char*)xmlSecKeyGetName(handle);
358+
if (cname != NULL) {
359+
return PyString_FromString(cname);
360+
}
361+
Py_RETURN_NONE;
358362
}
359363

360364
static int PyXmlSec_KeyNameSet(PyObject* self, PyObject* value, void* closure) {
@@ -517,6 +521,7 @@ static void PyXmlSec_KeysManager__del__(PyObject* self) {
517521
PYXMLSEC_DEBUGF("%p: delete KeysManager", self);
518522
PyXmlSec_KeysManager* manager = (PyXmlSec_KeysManager*)self;
519523
if (manager->handle != NULL) {
524+
PYXMLSEC_DEBUGF("%p: delete KeysManager handle - %p", self, manager->handle);
520525
xmlSecKeysMngrDestroy(manager->handle);
521526
}
522527
Py_TYPE(self)->tp_free(self);
@@ -528,7 +533,7 @@ static const char PyXmlSec_KeysManagerAddKey__doc__[] = \
528533
static PyObject* PyXmlSec_KeysManagerAddKey(PyObject* self, PyObject* args, PyObject* kwargs) {
529534
static char *kwlist[] = { "key", NULL};
530535

531-
PyXmlSec_Key* key;
536+
PyXmlSec_Key* key = NULL;
532537

533538
PYXMLSEC_DEBUGF("%p(%p): add key - start", self, ((PyXmlSec_KeysManager*)self)->handle);
534539
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:add_key", kwlist, PyXmlSec_KeyType, &key)) {
@@ -574,15 +579,18 @@ static const char PyXmlSec_KeysManagerLoadCert__doc__[] = \
574579
static PyObject* PyXmlSec_KeysManagerLoadCert(PyObject* self, PyObject* args, PyObject* kwargs) {
575580
static char *kwlist[] = { "filename", "format", "type", NULL};
576581

577-
const char* filename = NULL;
582+
PyObject* filepath = NULL;
578583
unsigned int format = 0;
579584
unsigned int type = 0;
580585

581586
PYXMLSEC_DEBUGF("%p: load cert - start", self);
582-
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sII:load_cert", kwlist, &filename, &format, &type)) {
587+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&II:load_cert", kwlist,
588+
PyString_FSConverter, &filepath, &format, &type)) {
583589
goto ON_FAIL;
584590
}
585591

592+
const char* filename = PyBytes_AsString(filepath);
593+
586594
int rv;
587595
Py_BEGIN_ALLOW_THREADS;
588596
rv = xmlSecCryptoAppKeysMngrCertLoad(((PyXmlSec_KeysManager*)self)->handle, filename, format, type);
@@ -591,10 +599,12 @@ static PyObject* PyXmlSec_KeysManagerLoadCert(PyObject* self, PyObject* args, Py
591599
PyXmlSec_SetLastError("cannot load cert");
592600
goto ON_FAIL;
593601
}
602+
Py_DECREF(filepath);
594603
PYXMLSEC_DEBUGF("%p: load cert - ok", self);
595604
Py_RETURN_NONE;
596605
ON_FAIL:
597606
PYXMLSEC_DEBUGF("%p: load cert - fail", self);
607+
Py_XDECREF(filepath);
598608
return NULL;
599609
}
600610

src/lxml.c

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "common.h"
1111
#include "lxml.h"
1212

13+
#include <etree_defs.h>
1314
#include <lxml.etree_api.h>
1415

1516
#include <libxml/xmlmemory.h>
@@ -21,6 +22,10 @@ int PyXmlSec_InitLxmlModule(void) {
2122
return import_lxml__etree();
2223
}
2324

25+
int PyXmlSec_IsElement(xmlNodePtr xnode) {
26+
return _isElement(xnode);
27+
}
28+
2429
PyXmlSec_LxmlElementPtr PyXmlSec_elementFactory(PyXmlSec_LxmlDocumentPtr doc, xmlNodePtr xnode) {
2530
return elementFactory(doc, xnode);
2631
}

src/lxml.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616
#include <libxml/valid.h>
1717

1818
#include <lxml-version.h>
19-
#include <etree_defs.h>
2019
#include <lxml.etree.h>
2120

2221
typedef struct LxmlElement* PyXmlSec_LxmlElementPtr;
2322
typedef struct LxmlDocument* PyXmlSec_LxmlDocumentPtr;
2423

24+
// checks that xnode is Element
25+
int PyXmlSec_IsElement(xmlNodePtr xnode);
2526
// creates a new element
2627
PyXmlSec_LxmlElementPtr PyXmlSec_elementFactory(PyXmlSec_LxmlDocumentPtr doc, xmlNodePtr node);
2728

src/template.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,28 @@ static char PyXmlSec_TemplateCreate__doc__[] = \
2323
":param node: the signature node\n"
2424
":param c14n_method: the signature canonicalization method\n"
2525
":param sign_method: the signature method\n"
26-
":param name: the node id (optional)\n"
26+
":param id: the node id (optional)\n"
2727
":param ns: the namespace prefix for the signature element (e.g. \"dsig\") (optional)\n"
2828
":return: the pointer to newly created <dsig:Signature/> node\n";
2929
static PyObject* PyXmlSec_TemplateCreate(PyObject* self, PyObject *args, PyObject *kwargs) {
30-
static char *kwlist[] = { "node", "c14n_method", "sign_method", "name", "ns", NULL};
30+
static char *kwlist[] = { "node", "c14n_method", "sign_method", "id", "ns", "name", NULL};
3131

3232
PyXmlSec_LxmlElementPtr node = NULL;
3333
PyXmlSec_Transform* c14n = NULL;
3434
PyXmlSec_Transform* sign = NULL;
35-
const char* name = NULL;
35+
const char* id = NULL;
3636
const char* ns = NULL;
3737

3838
PYXMLSEC_DEBUG("template create - start");
39-
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O!O!|zz:create", kwlist,
40-
PyXmlSec_LxmlElementConverter, &node, PyXmlSec_TransformType, &c14n, PyXmlSec_TransformType, &sign, &name, &ns))
39+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O!O!|zzz:create", kwlist,
40+
PyXmlSec_LxmlElementConverter, &node, PyXmlSec_TransformType, &c14n, PyXmlSec_TransformType, &sign, &id, &ns, &id))
4141
{
4242
goto ON_FAIL;
4343
}
4444

4545
xmlNodePtr res;
4646
Py_BEGIN_ALLOW_THREADS;
47-
res = xmlSecTmplSignatureCreateNsPref(node->_doc->_c_doc, c14n->id, sign->id, XSTR(name), XSTR(ns));
47+
res = xmlSecTmplSignatureCreateNsPref(node->_doc->_c_doc, c14n->id, sign->id, XSTR(id), XSTR(ns));
4848
Py_END_ALLOW_THREADS;
4949
if (res == NULL) {
5050
PyXmlSec_SetLastError("cannot create template.");
@@ -496,7 +496,7 @@ static PyObject* PyXmlSec_TemplateAddX509DataAddCRL(PyObject* self, PyObject *ar
496496
static char PyXmlSec_TemplateAddEncryptedKey__doc__[] = \
497497
"Adds <enc:EncryptedKey/> node with given attributes to the <dsig:KeyInfo/> node of *node*.\n\n"
498498
":param node: the pointer to <dsig:KeyInfo/> node\n"
499-
":param method: the encryption method (optional)\n"
499+
":param method: the encryption method\n"
500500
":param id: the Id attribute (optional)\n"
501501
":param type: the Type attribute (optional)\n"
502502
":param recipient: the Recipient attribute (optional)\n"
@@ -536,7 +536,7 @@ static PyObject* PyXmlSec_TemplateAddEncryptedKey(PyObject* self, PyObject *args
536536
static char PyXmlSec_TemplateCreateEncryptedData__doc__[] = \
537537
"Creates new <{ns}:EncryptedData /> node for encryption template.\n\n"
538538
":param node: the pointer to signature node\n"
539-
":param method: the encryption method (optional)\n"
539+
":param method: the encryption method\n"
540540
":param id: the Id attribute (optional)\n"
541541
":param type: the Type attribute (optional)\n"
542542
":param mime_type: the Recipient attribute (optional)\n"

src/tree.c

-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,6 @@ int PyXmlSec_TreeModule_Init(PyObject* package) {
232232

233233
if (!tree) goto ON_FAIL;
234234

235-
PYXMLSEC_DEBUGF("%", tree);
236235
if (PyModule_AddObject(package, "tree", tree) < 0) goto ON_FAIL;
237236

238237
return 0;

0 commit comments

Comments
 (0)