cookie: flush better

The cookie flushing (saving to a cookie jar) should only be done if a
transfer has been started. This is now done by checking the
cookies->running field, which is not reset in curl_easy_reset() so the
saving works correctly even after a call to that.

Follow-up to fd6eb8d6e7

Verified by test 1920

Reported-by: Alexander Batischev
Fixes #20090
Closes #20094
This commit is contained in:
Daniel Stenberg 2025-12-25 10:53:11 +01:00
parent e78a466ebd
commit 18af4e4e10
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
5 changed files with 138 additions and 16 deletions

View file

@ -1607,22 +1607,24 @@ struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
void Curl_flush_cookies(struct Curl_easy *data, bool cleanup) void Curl_flush_cookies(struct Curl_easy *data, bool cleanup)
{ {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
/* only save the cookie file if a transfer was started (data->state.url is /* only save the cookie file if a transfer was started (cookies->running is
set), as otherwise the cookies were not completely initialized and there set), as otherwise the cookies were not completely initialized and there
might be cookie files that were not loaded so saving the file is the wrong might be cookie files that were not loaded so saving the file is the
thing. */ wrong thing. */
if(data->set.str[STRING_COOKIEJAR] && Curl_bufref_ptr(&data->state.url)) { if(data->cookies) {
/* if we have a destination file for all the cookies to get dumped to */ if(data->set.str[STRING_COOKIEJAR] && data->cookies->running) {
CURLcode result = cookie_output(data, data->cookies, /* if we have a destination file for all the cookies to get dumped to */
data->set.str[STRING_COOKIEJAR]); CURLcode result = cookie_output(data, data->cookies,
if(result) data->set.str[STRING_COOKIEJAR]);
infof(data, "WARNING: failed to save cookies in %s: %s", if(result)
data->set.str[STRING_COOKIEJAR], curl_easy_strerror(result)); infof(data, "WARNING: failed to save cookies in %s: %s",
} data->set.str[STRING_COOKIEJAR], curl_easy_strerror(result));
}
if(cleanup && (!data->share || (data->cookies != data->share->cookies))) { if(cleanup && (!data->share || (data->cookies != data->share->cookies))) {
Curl_cookie_cleanup(data->cookies); Curl_cookie_cleanup(data->cookies);
data->cookies = NULL; data->cookies = NULL;
}
} }
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
} }

View file

@ -233,7 +233,7 @@ test1800 test1801 test1802 \
\ \
test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 \ test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 \
test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \ test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \
test1916 test1917 test1918 test1919 \ test1916 test1917 test1918 test1919 test1920 \
\ \
test1933 test1934 test1935 test1936 test1937 test1938 test1939 test1940 \ test1933 test1934 test1935 test1936 test1937 test1938 test1939 test1940 \
test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 \ test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 \

65
tests/data/test1920 Normal file
View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="US-ASCII"?>
<testcase>
<info>
<keywords>
cookies
</keywords>
</info>
<reply>
<data crlf="headers" nocheck="yes">
HTTP/1.1 200 OK
Date: Tue, 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
Set-Cookie: cookiename=cookiecontent;
-foo-
</data>
</reply>
# Client-side
<client>
<name>
load cookies, perform then reset before cleanup
</name>
<server>
http
</server>
<features>
cookies
</features>
<tool>
lib%TESTNUMBER
</tool>
<command>
http://%HOSTIP:%HTTPPORT/ %LOGDIR/cookie%TESTNUMBER
</command>
<file name="%LOGDIR/cookie%TESTNUMBER">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
example.com FALSE / FALSE 0 has_js 1
</file>
</client>
# Verify data after the test has been "shot"
<verify>
<file name="%LOGDIR/cookie%TESTNUMBER" mode="text">
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
%HOSTIP FALSE / FALSE 0 cookiename cookiecontent
example.com FALSE / FALSE 0 has_js 1
</file>
</verify>
</testcase>

View file

@ -103,7 +103,7 @@ TESTS_C = \
lib1662.c \ lib1662.c \
lib1900.c lib1901.c lib1902.c lib1903.c lib1905.c lib1906.c lib1907.c \ lib1900.c lib1901.c lib1902.c lib1903.c lib1905.c lib1906.c lib1907.c \
lib1908.c lib1910.c lib1911.c lib1912.c lib1913.c \ lib1908.c lib1910.c lib1911.c lib1912.c lib1913.c \
lib1915.c lib1916.c lib1918.c lib1919.c \ lib1915.c lib1916.c lib1918.c lib1919.c lib1920.c \
lib1933.c lib1934.c lib1935.c lib1936.c lib1937.c lib1938.c lib1939.c \ lib1933.c lib1934.c lib1935.c lib1936.c lib1937.c lib1938.c lib1939.c \
lib1940.c lib1945.c \ lib1940.c lib1945.c \
lib1947.c lib1948.c \ lib1947.c lib1948.c \

55
tests/libtest/lib1920.c Normal file
View file

@ -0,0 +1,55 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 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
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "first.h"
static CURLcode test_lib1920(const char *URL)
{
CURLcode result = CURLE_OK;
CURL *curl = NULL;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl) {
easy_setopt(curl, CURLOPT_COOKIEFILE, libtest_arg2);
easy_setopt(curl, CURLOPT_COOKIEJAR, libtest_arg2);
easy_setopt(curl, CURLOPT_URL, URL);
easy_setopt(curl, CURLOPT_VERBOSE, 1L);
result = curl_easy_perform(curl);
if(!result) {
/* doing a reset here should not change the cookie jar content */
curl_easy_reset(curl);
/* set the cookie jar name so that curl knows where to store the
cookies after reset */
easy_setopt(curl, CURLOPT_COOKIEJAR, libtest_arg2);
}
}
test_cleanup:
curl_easy_cleanup(curl);
curl_global_cleanup();
return result;
}