summaryrefslogtreecommitdiff
path: root/backport-CVE-2024-11053-pre2.patch
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2025-03-04 03:28:50 +0000
committerCoprDistGit <infra@openeuler.org>2025-03-04 03:28:50 +0000
commit510937df92473c5a6830d87f078386db8dbf896d (patch)
tree64d9befb90cb19890926aedd71df1a7a5452e08c /backport-CVE-2024-11053-pre2.patch
parentdbf64f99d0f0a31203092f9afdc6c07e13917313 (diff)
automatic import of curlopeneuler24.03_LTS_SP1
Diffstat (limited to 'backport-CVE-2024-11053-pre2.patch')
-rw-r--r--backport-CVE-2024-11053-pre2.patch800
1 files changed, 800 insertions, 0 deletions
diff --git a/backport-CVE-2024-11053-pre2.patch b/backport-CVE-2024-11053-pre2.patch
new file mode 100644
index 0000000..eff59cc
--- /dev/null
+++ b/backport-CVE-2024-11053-pre2.patch
@@ -0,0 +1,800 @@
+From 3b43a05e000aa8f65bda513f733a73fefe35d5ca Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel@haxx.se>
+Date: Thu, 10 Oct 2024 18:08:07 +0200
+Subject: [PATCH] netrc: cache the netrc file in memory
+
+So that on redirects etc it does not reread the file but just parses it
+again.
+
+Reported-by: Pierre-Etienne Meunier
+Fixes #15248
+Closes #15259
+
+Conflict:context adapt
+Reference:https://github.com/curl/curl/commit/3b43a05e000aa8f65bda513f733a73fefe35d5ca
+---
+ lib/multi.c | 2 +
+ lib/netrc.c | 407 ++++++++++++++++++++++++------------------
+ lib/netrc.h | 14 +-
+ lib/url.c | 4 +-
+ lib/urldata.h | 5 +
+ tests/unit/unit1304.c | 48 ++++-
+ 6 files changed, 292 insertions(+), 188 deletions(-)
+
+diff --git a/lib/multi.c b/lib/multi.c
+index 223c2339c..0f9fedaff 100644
+--- a/lib/multi.c
++++ b/lib/multi.c
+@@ -757,6 +757,8 @@ static CURLcode multi_done(struct Curl_easy *data,
+ data->state.lastconnect_id = -1;
+ }
+
++ /* flush the netrc cache */
++ Curl_netrc_cleanup(&data->state.netrc);
+ Curl_safefree(data->state.buffer);
+ return result;
+ }
+diff --git a/lib/netrc.c b/lib/netrc.c
+index 3c0651dcc..c23f927ce 100644
+--- a/lib/netrc.c
++++ b/lib/netrc.c
+@@ -31,7 +31,6 @@
+
+ #include <curl/curl.h>
+ #include "netrc.h"
+-#include "strtok.h"
+ #include "strcase.h"
+ #include "curl_get_line.h"
+
+@@ -49,21 +48,56 @@ enum host_lookup_state {
+ MACDEF
+ };
+
++enum found_state {
++ NONE,
++ LOGIN,
++ PASSWORD
++};
++
+ #define NETRC_FILE_MISSING 1
+ #define NETRC_FAILED -1
+ #define NETRC_SUCCESS 0
+
+ #define MAX_NETRC_LINE 4096
++#define MAX_NETRC_FILE (64*1024)
++#define MAX_NETRC_TOKEN 128
++
++static CURLcode file2memory(const char *filename, struct dynbuf *filebuf)
++{
++ CURLcode result = CURLE_OK;
++ FILE *file = fopen(filename, FOPEN_READTEXT);
++ struct dynbuf linebuf;
++ Curl_dyn_init(&linebuf, MAX_NETRC_LINE);
++
++ if(file) {
++ while(Curl_get_line(&linebuf, file)) {
++ const char *line = Curl_dyn_ptr(&linebuf);
++ /* skip comments on load */
++ while(ISBLANK(*line))
++ line++;
++ if(*line == '#')
++ continue;
++ result = Curl_dyn_add(filebuf, line);
++ if(result)
++ goto done;
++ }
++ }
++done:
++ Curl_dyn_free(&linebuf);
++ if(file)
++ fclose(file);
++ return result;
++}
+
+ /*
+ * Returns zero on success.
+ */
+-static int parsenetrc(const char *host,
++static int parsenetrc(struct store_netrc *store,
++ const char *host,
+ char **loginp,
+ char **passwordp,
+- char *netrcfile)
++ const char *netrcfile)
+ {
+- FILE *file;
+ int retcode = NETRC_FILE_MISSING;
+ char *login = *loginp;
+ char *password = *passwordp;
+@@ -71,204 +105,212 @@ static int parsenetrc(const char *host,
+ bool login_alloc = FALSE;
+ bool password_alloc = FALSE;
+ enum host_lookup_state state = NOTHING;
++ enum found_state found = NONE;
++ bool our_login = TRUE; /* With specific_login, found *our* login name (or
++ login-less line) */
++ bool done = FALSE;
++ char *netrcbuffer;
++ struct dynbuf token;
++ struct dynbuf *filebuf = &store->filebuf;
++ Curl_dyn_init(&token, MAX_NETRC_TOKEN);
+
+- char state_login = 0; /* Found a login keyword */
+- char state_password = 0; /* Found a password keyword */
+- int state_our_login = TRUE; /* With specific_login, found *our* login
+- name (or login-less line) */
+-
+- DEBUGASSERT(netrcfile);
++ if(!store->loaded) {
++ if(file2memory(netrcfile, filebuf))
++ return NETRC_FAILED;
++ store->loaded = TRUE;
++ }
+
+- file = fopen(netrcfile, FOPEN_READTEXT);
+- if(file) {
+- bool done = FALSE;
+- struct dynbuf buf;
+- Curl_dyn_init(&buf, MAX_NETRC_LINE);
++ netrcbuffer = Curl_dyn_ptr(filebuf);
+
+- while(!done && Curl_get_line(&buf, file)) {
+- char *tok;
++ while(!done) {
++ char *tok = netrcbuffer;
++ while(tok) {
+ char *tok_end;
+ bool quoted;
+- char *netrcbuffer = Curl_dyn_ptr(&buf);
++ Curl_dyn_reset(&token);
++ while(ISBLANK(*tok))
++ tok++;
++ /* tok is first non-space letter */
+ if(state == MACDEF) {
+- if((netrcbuffer[0] == '\n') || (netrcbuffer[0] == '\r'))
+- state = NOTHING;
+- else
+- continue;
++ if((*tok == '\n') || (*tok == '\r'))
++ state = NOTHING; /* end of macro definition */
+ }
+- tok = netrcbuffer;
+- while(tok) {
+- while(ISBLANK(*tok))
+- tok++;
+- /* tok is first non-space letter */
+- if(!*tok || (*tok == '#'))
+- /* end of line or the rest is a comment */
+- break;
+
+- /* leading double-quote means quoted string */
+- quoted = (*tok == '\"');
++ if(!*tok || (*tok == '\n'))
++ /* end of line */
++ break;
+
+- tok_end = tok;
+- if(!quoted) {
+- while(!ISSPACE(*tok_end))
+- tok_end++;
+- *tok_end = 0;
++ /* leading double-quote means quoted string */
++ quoted = (*tok == '\"');
++
++ tok_end = tok;
++ if(!quoted) {
++ size_t len = 0;
++ while(!ISSPACE(*tok_end)) {
++ tok_end++;
++ len++;
+ }
+- else {
+- bool escape = FALSE;
+- bool endquote = FALSE;
+- char *store = tok;
+- tok_end++; /* pass the leading quote */
+- while(*tok_end) {
+- char s = *tok_end;
+- if(escape) {
+- escape = FALSE;
+- switch(s) {
+- case 'n':
+- s = '\n';
+- break;
+- case 'r':
+- s = '\r';
+- break;
+- case 't':
+- s = '\t';
+- break;
+- }
+- }
+- else if(s == '\\') {
+- escape = TRUE;
+- tok_end++;
+- continue;
+- }
+- else if(s == '\"') {
+- tok_end++; /* pass the ending quote */
+- endquote = TRUE;
++ if(!len || Curl_dyn_addn(&token, tok, len)) {
++ retcode = NETRC_FAILED;
++ goto out;
++ }
++ }
++ else {
++ bool escape = FALSE;
++ bool endquote = FALSE;
++ tok_end++; /* pass the leading quote */
++ while(*tok_end) {
++ char s = *tok_end;
++ if(escape) {
++ escape = FALSE;
++ switch(s) {
++ case 'n':
++ s = '\n';
++ break;
++ case 'r':
++ s = '\r';
++ break;
++ case 't':
++ s = '\t';
+ break;
+ }
+- *store++ = s;
++ }
++ else if(s == '\\') {
++ escape = TRUE;
+ tok_end++;
++ continue;
++ }
++ else if(s == '\"') {
++ tok_end++; /* pass the ending quote */
++ endquote = TRUE;
++ break;
+ }
+- *store = 0;
+- if(escape || !endquote) {
+- /* bad syntax, get out */
++ if(Curl_dyn_addn(&token, &s, 1)) {
+ retcode = NETRC_FAILED;
+ goto out;
+ }
++ tok_end++;
+ }
+-
+- if((login && *login) && (password && *password)) {
+- done = TRUE;
+- break;
++ if(escape || !endquote) {
++ /* bad syntax, get out */
++ retcode = NETRC_FAILED;
++ goto out;
+ }
++ }
+
+- switch(state) {
+- case NOTHING:
+- if(strcasecompare("macdef", tok)) {
+- /* Define a macro. A macro is defined with the specified name; its
+- contents begin with the next .netrc line and continue until a
+- null line (consecutive new-line characters) is encountered. */
+- state = MACDEF;
+- }
+- else if(strcasecompare("machine", tok)) {
+- /* the next tok is the machine name, this is in itself the
+- delimiter that starts the stuff entered for this machine,
+- after this we need to search for 'login' and
+- 'password'. */
+- state = HOSTFOUND;
+- }
+- else if(strcasecompare("default", tok)) {
+- state = HOSTVALID;
+- retcode = NETRC_SUCCESS; /* we did find our host */
+- }
+- break;
+- case MACDEF:
+- if(!strlen(tok)) {
+- state = NOTHING;
+- }
+- break;
+- case HOSTFOUND:
+- if(strcasecompare(host, tok)) {
+- /* and yes, this is our host! */
+- state = HOSTVALID;
+- retcode = NETRC_SUCCESS; /* we did find our host */
++ if((login && *login) && (password && *password)) {
++ done = TRUE;
++ break;
++ }
++
++ tok = Curl_dyn_ptr(&token);
++
++ switch(state) {
++ case NOTHING:
++ if(strcasecompare("macdef", tok))
++ /* Define a macro. A macro is defined with the specified name; its
++ contents begin with the next .netrc line and continue until a
++ null line (consecutive new-line characters) is encountered. */
++ state = MACDEF;
++ else if(strcasecompare("machine", tok))
++ /* the next tok is the machine name, this is in itself the delimiter
++ that starts the stuff entered for this machine, after this we
++ need to search for 'login' and 'password'. */
++ state = HOSTFOUND;
++ else if(strcasecompare("default", tok)) {
++ state = HOSTVALID;
++ retcode = NETRC_SUCCESS; /* we did find our host */
++ }
++ break;
++ case MACDEF:
++ if(!*tok)
++ state = NOTHING;
++ break;
++ case HOSTFOUND:
++ if(strcasecompare(host, tok)) {
++ /* and yes, this is our host! */
++ state = HOSTVALID;
++ retcode = NETRC_SUCCESS; /* we did find our host */
++ }
++ else
++ /* not our host */
++ state = NOTHING;
++ break;
++ case HOSTVALID:
++ /* we are now parsing sub-keywords concerning "our" host */
++ if(found == LOGIN) {
++ if(specific_login) {
++ our_login = !Curl_timestrcmp(login, tok);
+ }
+- else
+- /* not our host */
+- state = NOTHING;
+- break;
+- case HOSTVALID:
+- /* we are now parsing sub-keywords concerning "our" host */
+- if(state_login) {
+- if(specific_login) {
+- state_our_login = !Curl_timestrcmp(login, tok);
++ else if(!login || Curl_timestrcmp(login, tok)) {
++ if(login_alloc)
++ free(login);
++ login = strdup(tok);
++ if(!login) {
++ retcode = NETRC_FAILED; /* allocation failed */
++ goto out;
+ }
+- else if(!login || Curl_timestrcmp(login, tok)) {
+- if(login_alloc) {
+- free(login);
+- login_alloc = FALSE;
+- }
+- login = strdup(tok);
+- if(!login) {
+- retcode = NETRC_FAILED; /* allocation failed */
+- goto out;
+- }
+- login_alloc = TRUE;
+- }
+- state_login = 0;
++ login_alloc = TRUE;
+ }
+- else if(state_password) {
+- if((state_our_login || !specific_login)
+- && (!password || Curl_timestrcmp(password, tok))) {
+- if(password_alloc) {
+- free(password);
+- password_alloc = FALSE;
+- }
+- password = strdup(tok);
+- if(!password) {
+- retcode = NETRC_FAILED; /* allocation failed */
+- goto out;
+- }
+- password_alloc = TRUE;
++ found = NONE;
++ }
++ else if(found == PASSWORD) {
++ if((our_login || !specific_login) &&
++ (!password || Curl_timestrcmp(password, tok))) {
++ if(password_alloc)
++ free(password);
++ password = strdup(tok);
++ if(!password) {
++ retcode = NETRC_FAILED; /* allocation failed */
++ goto out;
+ }
+- state_password = 0;
+- }
+- else if(strcasecompare("login", tok))
+- state_login = 1;
+- else if(strcasecompare("password", tok))
+- state_password = 1;
+- else if(strcasecompare("machine", tok)) {
+- /* ok, there's machine here go => */
+- state = HOSTFOUND;
+- state_our_login = FALSE;
++ password_alloc = TRUE;
+ }
+- break;
+- } /* switch (state) */
+- tok = ++tok_end;
+- }
+- } /* while Curl_get_line() */
++ found = NONE;
++ }
++ else if(strcasecompare("login", tok))
++ found = LOGIN;
++ else if(strcasecompare("password", tok))
++ found = PASSWORD;
++ else if(strcasecompare("machine", tok)) {
++ /* ok, there is machine here go => */
++ state = HOSTFOUND;
++ found = NONE;
++ }
++ break;
++ } /* switch (state) */
++ tok = ++tok_end;
++ }
++ if(!done) {
++ char *nl = NULL;
++ if(tok)
++ nl = strchr(tok, '\n');
++ if(!nl)
++ break;
++ /* point to next line */
++ netrcbuffer = &nl[1];
++ }
++ } /* while !done */
+
+ out:
+- Curl_dyn_free(&buf);
+- if(!retcode) {
+- /* success */
+- if(login_alloc) {
+- if(*loginp)
+- free(*loginp);
+- *loginp = login;
+- }
+- if(password_alloc) {
+- if(*passwordp)
+- free(*passwordp);
+- *passwordp = password;
+- }
++ Curl_dyn_free(&token);
++ if(!retcode) {
++ /* success */
++ if(login_alloc) {
++ free(*loginp);
++ *loginp = login;
+ }
+- else {
+- if(login_alloc)
+- free(login);
+- if(password_alloc)
+- free(password);
++ if(password_alloc) {
++ free(*passwordp);
++ *passwordp = password;
+ }
+- fclose(file);
++ }
++ else {
++ Curl_dyn_free(filebuf);
++ if(login_alloc)
++ free(login);
++ if(password_alloc)
++ free(password);
+ }
+
+ return retcode;
+@@ -280,7 +322,8 @@ out:
+ * *loginp and *passwordp MUST be allocated if they aren't NULL when passed
+ * in.
+ */
+-int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
++int Curl_parsenetrc(struct store_netrc *store, const char *host,
++ char **loginp, char **passwordp,
+ char *netrcfile)
+ {
+ int retcode = 1;
+@@ -329,7 +372,7 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
+ free(homea);
+ return -1;
+ }
+- retcode = parsenetrc(host, loginp, passwordp, filealloc);
++ retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
+ free(filealloc);
+ #ifdef WIN32
+ if(retcode == NETRC_FILE_MISSING) {
+@@ -339,15 +382,25 @@ int Curl_parsenetrc(const char *host, char **loginp, char **passwordp,
+ free(homea);
+ return -1;
+ }
+- retcode = parsenetrc(host, loginp, passwordp, filealloc);
++ retcode = parsenetrc(store, host, loginp, passwordp, filealloc);
+ free(filealloc);
+ }
+ #endif
+ free(homea);
+ }
+ else
+- retcode = parsenetrc(host, loginp, passwordp, netrcfile);
++ retcode = parsenetrc(store, host, loginp, passwordp, netrcfile);
+ return retcode;
+ }
+
++void Curl_netrc_init(struct store_netrc *s)
++{
++ Curl_dyn_init(&s->filebuf, MAX_NETRC_FILE);
++ s->loaded = FALSE;
++}
++void Curl_netrc_cleanup(struct store_netrc *s)
++{
++ Curl_dyn_free(&s->filebuf);
++ s->loaded = FALSE;
++}
+ #endif
+diff --git a/lib/netrc.h b/lib/netrc.h
+index 37c95db5e..0ef9ff78e 100644
+--- a/lib/netrc.h
++++ b/lib/netrc.h
+@@ -26,9 +26,19 @@
+
+ #include "curl_setup.h"
+ #ifndef CURL_DISABLE_NETRC
++#include "dynbuf.h"
++
++struct store_netrc {
++ struct dynbuf filebuf;
++ char *filename;
++ BIT(loaded);
++};
++
++void Curl_netrc_init(struct store_netrc *s);
++void Curl_netrc_cleanup(struct store_netrc *s);
+
+ /* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
+-int Curl_parsenetrc(const char *host, char **loginp,
++int Curl_parsenetrc(struct store_netrc *s, const char *host, char **loginp,
+ char **passwordp, char *filename);
+ /* Assume: (*passwordp)[0]=0, host[0] != 0.
+ * If (*loginp)[0] = 0, search for login and password within a machine
+@@ -38,6 +48,8 @@ int Curl_parsenetrc(const char *host, char **loginp,
+ #else
+ /* disabled */
+ #define Curl_parsenetrc(a,b,c,d,e,f) 1
++#define Curl_netrc_init(x)
++#define Curl_netrc_cleanup(x)
+ #endif
+
+ #endif /* HEADER_CURL_NETRC_H */
+diff --git a/lib/url.c b/lib/url.c
+index a59cb0e34..45745bc60 100644
+--- a/lib/url.c
++++ b/lib/url.c
+@@ -338,6 +338,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
+ Curl_wildcard_dtor(&data->wildcard);
+ Curl_freeset(data);
+ Curl_headers_cleanup(data);
++ Curl_netrc_cleanup(&data->state.netrc);
+ free(data);
+ return CURLE_OK;
+ }
+@@ -545,6 +546,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
+
+ data->progress.flags |= PGRS_HIDE;
+ data->state.current_speed = -1; /* init to negative == impossible */
++ Curl_netrc_init(&data->state.netrc);
+ }
+
+ if(result) {
+@@ -2689,7 +2691,7 @@ static CURLcode override_login(struct Curl_easy *data,
+ url_provided = TRUE;
+ }
+
+- ret = Curl_parsenetrc(conn->host.name,
++ ret = Curl_parsenetrc(&data->state.netrc, conn->host.name,
+ userp, passwdp,
+ data->set.str[STRING_NETRC_FILE]);
+ if(ret > 0) {
+diff --git a/lib/urldata.h b/lib/urldata.h
+index 4e0d6ef98..6aa26237d 100644
+--- a/lib/urldata.h
++++ b/lib/urldata.h
+@@ -163,6 +163,7 @@ typedef unsigned int curl_prot_t;
+ #include "splay.h"
+ #include "dynbuf.h"
+ #include "dynhds.h"
++#include "netrc.h"
+
+ /* return the count of bytes sent, or -1 on error */
+ typedef ssize_t (Curl_send)(struct Curl_easy *data, /* transfer */
+@@ -1313,6 +1314,10 @@ struct UrlState {
+ CURLcode hresult; /* used to pass return codes back from hyper callbacks */
+ #endif
+
++#ifndef CURL_DISABLE_NETRC
++ struct store_netrc netrc;
++#endif
++
+ /* Dynamically allocated strings, MUST be freed before this struct is
+ killed. */
+ struct dynamically_allocated_data {
+diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c
+index 2171c0736..238d3c0f7 100644
+--- a/tests/unit/unit1304.c
++++ b/tests/unit/unit1304.c
+@@ -49,17 +49,22 @@ static void unit_stop(void)
+ }
+
+ UNITTEST_START
++{
+ int result;
++ struct store_netrc store;
+
+ /*
+ * Test a non existent host in our netrc file.
+ */
+- result = Curl_parsenetrc("test.example.com", &login, &password, arg);
++ Curl_netrc_init(&store);
++ result = Curl_parsenetrc(&store,
++ "test.example.com", &login, &password, arg);
+ fail_unless(result == 1, "Host not found should return 1");
+ abort_unless(password != NULL, "returned NULL!");
+ fail_unless(password[0] == 0, "password should not have been changed");
+ abort_unless(login != NULL, "returned NULL!");
+ fail_unless(login[0] == 0, "login should not have been changed");
++ Curl_netrc_cleanup(&store);
+
+ /*
+ * Test a non existent login in our netrc file.
+@@ -67,13 +72,16 @@ UNITTEST_START
+ free(login);
+ login = strdup("me");
+ abort_unless(login != NULL, "returned NULL!");
+- result = Curl_parsenetrc("example.com", &login, &password, arg);
++ Curl_netrc_init(&store);
++ result = Curl_parsenetrc(&store,
++ "example.com", &login, &password, arg);
+ fail_unless(result == 0, "Host should have been found");
+ abort_unless(password != NULL, "returned NULL!");
+ fail_unless(password[0] == 0, "password should not have been changed");
+ abort_unless(login != NULL, "returned NULL!");
+ fail_unless(strncmp(login, "me", 2) == 0,
+ "login should not have been changed");
++ Curl_netrc_cleanup(&store);
+
+ /*
+ * Test a non existent login and host in our netrc file.
+@@ -81,13 +89,16 @@ UNITTEST_START
+ free(login);
+ login = strdup("me");
+ abort_unless(login != NULL, "returned NULL!");
+- result = Curl_parsenetrc("test.example.com", &login, &password, arg);
++ Curl_netrc_init(&store);
++ result = Curl_parsenetrc(&store,
++ "test.example.com", &login, &password, arg);
+ fail_unless(result == 1, "Host not found should return 1");
+ abort_unless(password != NULL, "returned NULL!");
+ fail_unless(password[0] == 0, "password should not have been changed");
+ abort_unless(login != NULL, "returned NULL!");
+ fail_unless(strncmp(login, "me", 2) == 0,
+ "login should not have been changed");
++ Curl_netrc_cleanup(&store);
+
+ /*
+ * Test a non existent login (substring of an existing one) in our
+@@ -96,13 +107,16 @@ UNITTEST_START
+ free(login);
+ login = strdup("admi");
+ abort_unless(login != NULL, "returned NULL!");
+- result = Curl_parsenetrc("example.com", &login, &password, arg);
++ Curl_netrc_init(&store);
++ result = Curl_parsenetrc(&store,
++ "example.com", &login, &password, arg);
+ fail_unless(result == 0, "Host should have been found");
+ abort_unless(password != NULL, "returned NULL!");
+ fail_unless(password[0] == 0, "password should not have been changed");
+ abort_unless(login != NULL, "returned NULL!");
+ fail_unless(strncmp(login, "admi", 4) == 0,
+ "login should not have been changed");
++ Curl_netrc_cleanup(&store);
+
+ /*
+ * Test a non existent login (superstring of an existing one)
+@@ -111,13 +125,16 @@ UNITTEST_START
+ free(login);
+ login = strdup("adminn");
+ abort_unless(login != NULL, "returned NULL!");
+- result = Curl_parsenetrc("example.com", &login, &password, arg);
++ Curl_netrc_init(&store);
++ result = Curl_parsenetrc(&store,
++ "example.com", &login, &password, arg);
+ fail_unless(result == 0, "Host should have been found");
+ abort_unless(password != NULL, "returned NULL!");
+ fail_unless(password[0] == 0, "password should not have been changed");
+ abort_unless(login != NULL, "returned NULL!");
+ fail_unless(strncmp(login, "adminn", 6) == 0,
+ "login should not have been changed");
++ Curl_netrc_cleanup(&store);
+
+ /*
+ * Test for the first existing host in our netrc file
+@@ -126,13 +143,16 @@ UNITTEST_START
+ free(login);
+ login = strdup("");
+ abort_unless(login != NULL, "returned NULL!");
+- result = Curl_parsenetrc("example.com", &login, &password, arg);
++ Curl_netrc_init(&store);
++ result = Curl_parsenetrc(&store,
++ "example.com", &login, &password, arg);
+ fail_unless(result == 0, "Host should have been found");
+ abort_unless(password != NULL, "returned NULL!");
+ fail_unless(strncmp(password, "passwd", 6) == 0,
+ "password should be 'passwd'");
+ abort_unless(login != NULL, "returned NULL!");
+ fail_unless(strncmp(login, "admin", 5) == 0, "login should be 'admin'");
++ Curl_netrc_cleanup(&store);
+
+ /*
+ * Test for the first existing host in our netrc file
+@@ -141,13 +161,16 @@ UNITTEST_START
+ free(password);
+ password = strdup("");
+ abort_unless(password != NULL, "returned NULL!");
+- result = Curl_parsenetrc("example.com", &login, &password, arg);
++ Curl_netrc_init(&store);
++ result = Curl_parsenetrc(&store,
++ "example.com", &login, &password, arg);
+ fail_unless(result == 0, "Host should have been found");
+ abort_unless(password != NULL, "returned NULL!");
+ fail_unless(strncmp(password, "passwd", 6) == 0,
+ "password should be 'passwd'");
+ abort_unless(login != NULL, "returned NULL!");
+ fail_unless(strncmp(login, "admin", 5) == 0, "login should be 'admin'");
++ Curl_netrc_cleanup(&store);
+
+ /*
+ * Test for the second existing host in our netrc file
+@@ -159,13 +182,16 @@ UNITTEST_START
+ free(login);
+ login = strdup("");
+ abort_unless(login != NULL, "returned NULL!");
+- result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
++ Curl_netrc_init(&store);
++ result = Curl_parsenetrc(&store,
++ "curl.example.com", &login, &password, arg);
+ fail_unless(result == 0, "Host should have been found");
+ abort_unless(password != NULL, "returned NULL!");
+ fail_unless(strncmp(password, "none", 4) == 0,
+ "password should be 'none'");
+ abort_unless(login != NULL, "returned NULL!");
+ fail_unless(strncmp(login, "none", 4) == 0, "login should be 'none'");
++ Curl_netrc_cleanup(&store);
+
+ /*
+ * Test for the second existing host in our netrc file
+@@ -174,14 +200,18 @@ UNITTEST_START
+ free(password);
+ password = strdup("");
+ abort_unless(password != NULL, "returned NULL!");
+- result = Curl_parsenetrc("curl.example.com", &login, &password, arg);
++ Curl_netrc_init(&store);
++ result = Curl_parsenetrc(&store,
++ "curl.example.com", &login, &password, arg);
+ fail_unless(result == 0, "Host should have been found");
+ abort_unless(password != NULL, "returned NULL!");
+ fail_unless(strncmp(password, "none", 4) == 0,
+ "password should be 'none'");
+ abort_unless(login != NULL, "returned NULL!");
+ fail_unless(strncmp(login, "none", 4) == 0, "login should be 'none'");
++ Curl_netrc_cleanup(&store);
+
++}
+ UNITTEST_STOP
+
+ #else
+--
+2.33.0
+