From d48e6b7f9558ae2a21c74f9054221af8f5c6b607 Mon Sep 17 00:00:00 2001
From: Michael Kaufmann <mail@michael-kaufmann.ch>
Date: Wed, 10 Oct 2018 22:38:50 +0200
Subject: [PATCH 200/557] netrc: free temporary strings if memory allocation
 fails

- Change the inout parameters after all needed memory has been
  allocated. Do not change them if something goes wrong.
- Free the allocated temporary strings if strdup() fails.

Closes #3122
---
 lib/netrc.c | 48 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 39 insertions(+), 9 deletions(-)

diff --git a/lib/netrc.c b/lib/netrc.c
index a407bda..1724b35 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -57,7 +57,11 @@ int Curl_parsenetrc(const char *host,
 {
   FILE *file;
   int retcode = 1;
-  int specific_login = (*loginp && **loginp != 0);
+  char *login = *loginp;
+  char *password = *passwordp;
+  bool specific_login = (login && *login != 0);
+  bool login_alloc = FALSE;
+  bool password_alloc = FALSE;
   bool netrc_alloc = FALSE;
   enum host_lookup_state state = NOTHING;
 
@@ -125,7 +129,7 @@ int Curl_parsenetrc(const char *host,
         continue;
       while(!done && tok) {
 
-        if((*loginp && **loginp) && (*passwordp && **passwordp)) {
+        if((login && *login) && (password && *password)) {
           done = TRUE;
           break;
         }
@@ -158,26 +162,34 @@ int Curl_parsenetrc(const char *host,
           /* we are now parsing sub-keywords concerning "our" host */
           if(state_login) {
             if(specific_login) {
-              state_our_login = strcasecompare(*loginp, tok);
+              state_our_login = strcasecompare(login, tok);
             }
             else {
-              free(*loginp);
-              *loginp = strdup(tok);
-              if(!*loginp) {
+              if(login_alloc) {
+                free(login);
+                login_alloc = FALSE;
+              }
+              login = strdup(tok);
+              if(!login) {
                 retcode = -1; /* allocation failed */
                 goto out;
               }
+              login_alloc = TRUE;
             }
             state_login = 0;
           }
           else if(state_password) {
             if(state_our_login || !specific_login) {
-              free(*passwordp);
-              *passwordp = strdup(tok);
-              if(!*passwordp) {
+              if(password_alloc) {
+                free(password);
+                password_alloc = FALSE;
+              }
+              password = strdup(tok);
+              if(!password) {
                 retcode = -1; /* allocation failed */
                 goto out;
               }
+              password_alloc = TRUE;
             }
             state_password = 0;
           }
@@ -198,6 +210,24 @@ int Curl_parsenetrc(const char *host,
     } /* while fgets() */
 
     out:
+    if(!retcode) {
+      if(login_alloc) {
+        if(*loginp)
+          free(*loginp);
+        *loginp = login;
+      }
+      if(password_alloc) {
+        if(*passwordp)
+          free(*passwordp);
+        *passwordp = password;
+      }
+    }
+    else {
+      if(login_alloc)
+        free(login);
+      if(password_alloc)
+        free(password);
+    }
     fclose(file);
   }
 
-- 
1.8.3.1

