Commit 409f2a04 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

fixed memory leak: CURLOPT_RESOLVE with multi interface

DNS cache entries populated with CURLOPT_RESOLVE were not properly freed
again when done using the multi interface.

Test case 1502 added to verify.

Bug: http://curl.haxx.se/bug/view.cgi?id=3575448
Reported by: Alex Gruz
parent dd75cba3
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
@@ -740,14 +740,18 @@ static int hostcache_inuse(void *data, void *hc)
  return 1; /* free all entries */
}

void Curl_hostcache_destroy(struct SessionHandle *data)
void Curl_hostcache_clean(struct SessionHandle *data)
{
  /* Entries added to the hostcache with the CURLOPT_RESOLVE function are
   * still present in the cache with the inuse counter set to 1. Detect them
   * and cleanup!
   */
  Curl_hash_clean_with_criterium(data->dns.hostcache, data, hostcache_inuse);
}

void Curl_hostcache_destroy(struct SessionHandle *data)
{
  Curl_hostcache_clean(data);
  Curl_hash_destroy(data->dns.hostcache);
  data->dns.hostcachetype = HCACHE_NONE;
  data->dns.hostcache = NULL;
+9 −1
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
@@ -200,11 +200,19 @@ extern sigjmp_buf curl_jmpenv;
 */
CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers);

/*
 * Clean off entries from the cache
 */
void Curl_hostcache_clean(struct SessionHandle *data);

/*
 * Destroy the hostcache of this handle.
 */
void Curl_hostcache_destroy(struct SessionHandle *data);

/*
 * Populate the cache with specified entries from CURLOPT_RESOLVE.
 */
CURLcode Curl_loadhostpairs(struct SessionHandle *data);

#endif /* HEADER_CURL_HOSTIP_H */
+4 −9
Original line number Diff line number Diff line
@@ -1789,12 +1789,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
  } WHILE_FALSE; /* just to break out from! */

  if(CURLM_STATE_COMPLETED == easy->state) {
    if(data->dns.hostcachetype == HCACHE_MULTI) {
      /* clear out the usage of the shared DNS cache */
      data->dns.hostcache = NULL;
      data->dns.hostcachetype = HCACHE_NONE;
    }

    /* now fill in the Curl_message with this info */
    msg = &easy->msg;

@@ -1911,9 +1905,6 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
      cl= n;
    }

    Curl_hash_destroy(multi->hostcache);
    multi->hostcache = NULL;

    Curl_hash_destroy(multi->sockhash);
    multi->sockhash = NULL;

@@ -1930,6 +1921,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
      nexteasy=easy->next;
      if(easy->easy_handle->dns.hostcachetype == HCACHE_MULTI) {
        /* clear out the usage of the shared DNS cache */
        Curl_hostcache_clean(easy->easy_handle);
        easy->easy_handle->dns.hostcache = NULL;
        easy->easy_handle->dns.hostcachetype = HCACHE_NONE;
      }
@@ -1943,6 +1935,9 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
      easy = nexteasy;
    }

    Curl_hash_destroy(multi->hostcache);
    multi->hostcache = NULL;

    free(multi);

    return CURLM_OK;
+1 −1
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ test1379 test1380 test1381 test1382 test1383 test1384 test1385 test1386 \
test1387 test1388 test1389 test1390 test1391 test1392 test1393 \
test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \
test1408 test1409 test1410 test1411 test1412 test1413 \
test1500 test1501 \
test1500 test1501 test1502 \
test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
test2016 test2017 test2018 test2019 test2020 test2021 test2022 \

tests/data/test1502

0 → 100644
+58 −0
Original line number Diff line number Diff line
<testcase>
<info>
<keywords>
HTTP
HTTP GET
multi
CURLOPT_RESOLVE
</keywords>
</info>

<reply>
<data>
HTTP/1.1 200 OK
Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake
Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
ETag: "21025-dc7-39462498"
Accept-Ranges: bytes
Content-Length: 6
Connection: close
Content-Type: text/html
Funny-head: yesyes

-foo-
</data>
</reply>

#
# Client-side
<client>
<server>
http
</server>
<tool>
lib1502
</tool>
 <name>
HTTP multi with CURLOPT_RESOLVE
 </name>
 <command>
http://google.com:%HTTPPORT/1502 %HTTPPORT %HOSTIP
</command>
</client>

#
# Verify data after the test has been "shot"
<verify>
<strip>
^User-Agent:.*
</strip>
<protocol>
GET /1502 HTTP/1.1
Host: google.com:%HTTPPORT
Accept: */*

</protocol>
</verify>
</testcase>
Loading