Double free memory in curlapi.c
Development toolkit for Web Services and XML data bindings for C & C++
Brought to you by:
engelen
Hello,
We are faced with double free issue in cURL integration code. It leads to segmentation fault:
Starting program: /data/myget http://1.2.3.4/source.svc [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". Downloading: Program received signal SIGSEGV, Segmentation fault. 0x00002aaaaea68005 in soap_end_block (soap=0x7ffffffd6978, b=0x89e530) at stdsoap2.cpp:2907 2907 stdsoap2.cpp: No such file or directory. (gdb) bt # 0 0x00002aaaaea68005 in soap_end_block (soap=0x7ffffffd6978, b=0x89e530) at stdsoap2.cpp:2907 # 1 0x00000000005eb1fb in soap_curl_delete (soap=0x7ffffffd6978, p=<optimized out>) at ../../webservice/curlapi.cpp:390 # 2 0x00002aaaaea6c6ab in soap_done (soap=0x7ffffffd6978) at stdsoap2.cpp:6203 # 3 0x00002aaaaea8cde4 in soap::~soap (this=0x7ffffffd6978, __in_chrg=<optimized out>) at stdsoap2.cpp:20295 # 4 0x00000000005dd8ab in Item::~Item (this=0x7ffffffd6900, __in_chrg=<optimized out>) at ../Item.cpp:15 # 5 0x00000000004f4c3d in main (argc=7, argv=0x7fffffffe478) at Main.cpp:358 (gdb) f 1 # 1 0x00000000005eb1fb in soap_curl_delete (soap=0x7ffffffd6978, p=<optimized out>) at ../curlapi.cpp:390 390 ../../webservice/curlapi.cpp: No such file or directory. (gdb) print *data $1 = {soap = 0x7ffffffd6978, curl = 0x895680, own = 0, active = 1, hdr = 0x0, blk = 0x0, ptr = 0x0, lst = 0x89e530, mode = 0, buf = "Operation timed out after 60000 milliseconds with 39021654 bytes received", '\000' <repeats 182 times>, fconnect = 0x0, fsend = 0x2aaaaea63288 <fsend(soap*, char const*, size_t)>, frecv = 0x2aaaaea63eae <frecv(soap*, char*, size_t)>, fprepareinitrecv = 0x0, fpreparefinalrecv = 0x0} (gdb)
Our platform:
gSOAP 2.8.54
GCC 4.9.3
Linux linux-host 2.6.32-431.5.1.el6.x86_64 #1 SMP Tue Feb 11 11:09:04 PST 2014 x86_64 x86_64 x86_64 GNU/Linux
plugin/curlapi.c was renamed to curlapi.cpp for easy integration with g++ and our CXXFLAGS.
The issue can be reproduced when downloading via cURl failed by timeout and void soap::destroy() was already executed in Item::~Item().
Double free can be fixed by next change in curlapi.c:
static void soap_curl_delete(struct soap *soap, struct soap_plugin *p) { (void)soap; struct soap_curl_data *data = (struct soap_curl_data*)p->data; DBGFUN("soap_curl_delete"); - if (data->lst) + if (soap->blist && data->lst) soap_end_block(soap, data->lst); if (data->curl && data->own) curl_easy_cleanup(data->curl); soap->fsend = data->fsend; soap->frecv = data->frecv; soap->fprepareinitrecv = data->fprepareinitrecv; soap->fpreparefinalrecv = data->fpreparefinalrecv; SOAP_FREE(soap, data); }
Best regards
Pavel Karneliuk
Here is a better solution that avoids this problem:
Interesting and yes this is a problem that will be fixed in 2.8.60 available soon. The fix differs from your approach, since we need to make sure this is also corrected even when
soap->blist
is NULL.