Skip to content

COOKIEFILE+COOKIEJAR may truncate cookie jar when no transfer occurs #18621

@divinity76

Description

@divinity76

I did this

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>     // mkstemp, close
#include <fcntl.h>      // write
#include <curl/curl.h>
#include <stdbool.h>

void xcurl_setopt(CURL *curl, CURLoption option, const char *value) {
    CURLcode rc = curl_easy_setopt(curl, option, value);
    if (rc != CURLE_OK) {
        fprintf(stderr, "curl_easy_setopt failed: %s\n", curl_easy_strerror(rc));
        curl_easy_cleanup(curl);
        curl_global_cleanup();
        exit(1);
    }
}
int main(int argc, char **argv) {
    const bool reload = argc > 1 && strcmp(argv[1], "RELOAD") == 0;
    // 1) Create a temp file path safely (mkstemp creates the file)
    char tmpl[] = "/tmp/cookieXXXXXX";
    int fd = mkstemp(tmpl);
    if (fd == -1) {
        perror("mkstemp");
        return 1;
    }

    // 2) Prepare cookie file contents
    const char *cookie =
        "# Netscape HTTP Cookie File\n"
        "# https://curl.se/docs/http-cookies.html\n"
        "# This file was generated by libcurl! Edit at your own risk.\n"
        "\n"
        "example.com\tFALSE\t/\tFALSE\t0\thas_js\t1\n";

    ssize_t to_write = (ssize_t)strlen(cookie);
    if (write(fd, cookie, to_write) != to_write) {
        perror("write");
        close(fd);
        unlink(tmpl);
        return 1;
    }

    // Ensure data hits disk
    if (fsync(fd) != 0) {
        perror("fsync");
        close(fd);
        unlink(tmpl);
        return 1;
    }
    close(fd);

    // 3) Initialize libcurl
    CURLcode rc;
    rc = curl_global_init(CURL_GLOBAL_DEFAULT);
    if (rc != CURLE_OK) {
        fprintf(stderr, "curl_global_init failed: %s\n", curl_easy_strerror(rc));
        unlink(tmpl);
        return 1;
    }

    CURL *curl = curl_easy_init();
    if (!curl) {
        fprintf(stderr, "curl_easy_init failed\n");
        curl_global_cleanup();
        unlink(tmpl);
        return 1;
    }

    // Point both options at the cookie file we just created
    xcurl_setopt(curl, CURLOPT_COOKIEFILE, tmpl);
    xcurl_setopt(curl, CURLOPT_COOKIEJAR,  tmpl);
    if (reload) {
        xcurl_setopt(curl, CURLOPT_COOKIELIST, "RELOAD");
    }

    // Do not perform any actual network operation,
    // the issue occur when not calling curl.*perform
    curl_easy_cleanup(curl);
    curl_global_cleanup();

    // 4) Read the cookie file back and print it (like PHP's var_dump(file_get_contents))
    FILE *fp = fopen(tmpl, "rb");
    if (!fp) {
        perror("fopen");
        unlink(tmpl);
        return 1;
    }

    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    char *buf = (char *)malloc((size_t)size + 1);
    if (!buf) {
        fprintf(stderr, "malloc failed\n");
        fclose(fp);
        unlink(tmpl);
        return 1;
    }

    fread(buf, 1, (size_t)size, fp);
    buf[size] = '\0';
    fclose(fp);
    printf("strlen %ld\n%s", size, buf);
    free(buf);
    unlink(tmpl);
    return 0;
}

and

hans@DESKTOP-EE15SLU:~/projects/autodata/hans$ gcc repro.c -lcurl
hans@DESKTOP-EE15SLU:~/projects/autodata/hans$ ./a.out RELOAD
strlen 168
# 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
hans@DESKTOP-EE15SLU:~/projects/autodata/hans$ ./a.out
strlen 131
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

I expected the following

I expected curl to not erase my cookiejar.

curl/libcurl version

curl version: libcurl/8.5.0 OpenSSL/3.0.13 zlib/1.3 brotli/1.1.0 zstd/1.5.5 libidn2/2.3.7 libpsl/0.21.2 (+libidn2/2.3.7) libssh/0.10.6/openssl/zlib nghttp2/1.59.0 librtmp/2.3 OpenLDAP/2.6.7

operating system

Ubuntu 24.04 x86-64

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions