Menu

#1185 Double free memory in curlapi.c

v1.0 (example)
closed-fixed
5
2018-01-28
2018-01-17
No

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

Discussion

  • Robert van Engelen

    • status: open --> open-accepted
     
  • Robert van Engelen

    Here is a better solution that avoids this problem:

    static size_t soap_curl_write_callback(void *buffer, size_t size, size_t nitems, void *ptr)
    {
      ...
      if (!data->lst)
      {
        /* store data received in an isolated blist */
        if (!(data->lst = soap_alloc_block(soap))) /* updated */
          return 0; /* updated */
        soap->blist = soap->blist->next; /* updated */
      }
    
     
  • Robert van Engelen

    • status: open-accepted --> pending-fixed
     
  • Robert van Engelen

    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.

     
  • Robert van Engelen

    • status: pending-fixed --> closed-fixed
     

Log in to post a comment.