Hi, I just started using PyAES and found some
serious memory leaks. Both are in rijndael_wrap.c. I don't have the code on
this machine but the problem was in the wrapper
functions for padEncrypt and padDecrypt.
The first leak was where it said
char **buf;
buf = malloc(i);
PyStringBytesAndSize(buf,&len,...)
or something like that. The malloc is simply
incorrect and the memory is never freed.
Correct is to say
char *buf;
PyStringBytesAndSize(&buf, &len,...).
The second leak is the safeString return value
from the pad(En|De)crypt functions, which consist
of two malloc'd objects. The comment in
rijndael-api-fst.c that says Python will free
the memory is incorrect. Python copies the
data into its own allocation system and leaves the
safeString alone, so it's never freed. The
wrap function needs to free the safeString buffers.
The result of the above leaks is that every time
you encrypt or decrypt a buffer, enough memory
to hold two copies of the buffer gets leaked,
i.e. if you encrypt a 1 MB buffer, you leak 2MB.
My application was encrypting large buffers
repeatedly so it quickly made my machine thrash.
That's what made me notice the problem.
Since I was doing a lot of encryption and not much
key initialization/creation, I didn't check the
key creation routines for leaks. I don't understand Python internals very well, and don't
have a copy of Swig installed on that system for
now (and it's not on the net). So I ended up
having to modify the rijndael_wrap.c file directly
rather than regenerating it.
Sorry I can't easily submit a directly useable
patch right now, but the above should be enough
to let you know how to fix the problem.
Paul Rubin
Fort GNOX Cryptography
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi, I just started using PyAES and found some
serious memory leaks. Both are in rijndael_wrap.c. I don't have the code on
this machine but the problem was in the wrapper
functions for padEncrypt and padDecrypt.
The first leak was where it said
char **buf;
buf = malloc(i);
PyStringBytesAndSize(buf,&len,...)
or something like that. The malloc is simply
incorrect and the memory is never freed.
Correct is to say
char *buf;
PyStringBytesAndSize(&buf, &len,...).
The second leak is the safeString return value
from the pad(En|De)crypt functions, which consist
of two malloc'd objects. The comment in
rijndael-api-fst.c that says Python will free
the memory is incorrect. Python copies the
data into its own allocation system and leaves the
safeString alone, so it's never freed. The
wrap function needs to free the safeString buffers.
The result of the above leaks is that every time
you encrypt or decrypt a buffer, enough memory
to hold two copies of the buffer gets leaked,
i.e. if you encrypt a 1 MB buffer, you leak 2MB.
My application was encrypting large buffers
repeatedly so it quickly made my machine thrash.
That's what made me notice the problem.
Since I was doing a lot of encryption and not much
key initialization/creation, I didn't check the
key creation routines for leaks. I don't understand Python internals very well, and don't
have a copy of Swig installed on that system for
now (and it's not on the net). So I ended up
having to modify the rijndael_wrap.c file directly
rather than regenerating it.
Sorry I can't easily submit a directly useable
patch right now, but the above should be enough
to let you know how to fix the problem.
Paul Rubin
Fort GNOX Cryptography
Thanks Paul!
I fixed the horrible mistake in my new project:
CryptKit.
http://www.sourceforge.net/projects/cryptkit/
Thanks Paul!
I fixed the horrible mistake in my new project:
CryptKit.
http://www.sourceforge.net/projects/cryptkit/