Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3172eea

Browse files
committed
Clean up password prompting logic in streamutil.c.
The previous coding was fairly unreadable and drew double-free warnings from clang. I believe the double free was actually not reachable, because PQconnectionNeedsPassword is coded to not return true if a password was provided, so that the loop can't iterate more than twice. Nonetheless it seems worth rewriting. No back-patch since this is just cosmetic.
1 parent f3b3b8d commit 3172eea

File tree

1 file changed

+56
-54
lines changed

1 file changed

+56
-54
lines changed

src/bin/pg_basebackup/streamutil.c

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ GetConnection(void)
4040
int i;
4141
const char **keywords;
4242
const char **values;
43-
char *password = NULL;
4443
const char *tmpparam;
44+
bool need_password;
4545
PQconninfoOption *conn_opts = NULL;
4646
PQconninfoOption *conn_opt;
4747
char *err_msg = NULL;
@@ -114,27 +114,30 @@ GetConnection(void)
114114
i++;
115115
}
116116

117+
/* If -W was given, force prompt for password, but only the first time */
118+
need_password = (dbgetpassword == 1 && dbpassword == NULL);
119+
117120
while (true)
118121
{
119-
if (password)
120-
free(password);
122+
/* Get a new password if appropriate */
123+
if (need_password)
124+
{
125+
if (dbpassword)
126+
free(dbpassword);
127+
dbpassword = simple_prompt(_("Password: "), 100, false);
128+
need_password = false;
129+
}
121130

131+
/* Use (or reuse, on a subsequent connection) password if we have it */
122132
if (dbpassword)
123133
{
124-
/*
125-
* We've saved a password when a previous connection succeeded,
126-
* meaning this is the call for a second session to the same
127-
* database, so just forcibly reuse that password.
128-
*/
129134
keywords[i] = "password";
130135
values[i] = dbpassword;
131-
dbgetpassword = -1; /* Don't try again if this fails */
132136
}
133-
else if (dbgetpassword == 1)
137+
else
134138
{
135-
password = simple_prompt(_("Password: "), 100, false);
136-
keywords[i] = "password";
137-
values[i] = password;
139+
keywords[i] = NULL;
140+
values[i] = NULL;
138141
}
139142

140143
tmpconn = PQconnectdbParams(keywords, values, true);
@@ -150,63 +153,62 @@ GetConnection(void)
150153
exit(1);
151154
}
152155

156+
/* If we need a password and -w wasn't given, loop back and get one */
153157
if (PQstatus(tmpconn) == CONNECTION_BAD &&
154158
PQconnectionNeedsPassword(tmpconn) &&
155159
dbgetpassword != -1)
156160
{
157-
dbgetpassword = 1; /* ask for password next time */
158-
PQfinish(tmpconn);
159-
continue;
160-
}
161-
162-
if (PQstatus(tmpconn) != CONNECTION_OK)
163-
{
164-
fprintf(stderr, _("%s: could not connect to server: %s\n"),
165-
progname, PQerrorMessage(tmpconn));
166161
PQfinish(tmpconn);
167-
free(values);
168-
free(keywords);
169-
if (conn_opts)
170-
PQconninfoFree(conn_opts);
171-
return NULL;
162+
need_password = true;
172163
}
164+
else
165+
break;
166+
}
173167

174-
/* Connection ok! */
168+
if (PQstatus(tmpconn) != CONNECTION_OK)
169+
{
170+
fprintf(stderr, _("%s: could not connect to server: %s\n"),
171+
progname, PQerrorMessage(tmpconn));
172+
PQfinish(tmpconn);
175173
free(values);
176174
free(keywords);
177175
if (conn_opts)
178176
PQconninfoFree(conn_opts);
177+
return NULL;
178+
}
179179

180-
/*
181-
* Ensure we have the same value of integer timestamps as the server
182-
* we are connecting to.
183-
*/
184-
tmpparam = PQparameterStatus(tmpconn, "integer_datetimes");
185-
if (!tmpparam)
186-
{
187-
fprintf(stderr,
188-
_("%s: could not determine server setting for integer_datetimes\n"),
189-
progname);
190-
PQfinish(tmpconn);
191-
exit(1);
192-
}
180+
/* Connection ok! */
181+
free(values);
182+
free(keywords);
183+
if (conn_opts)
184+
PQconninfoFree(conn_opts);
185+
186+
/*
187+
* Ensure we have the same value of integer timestamps as the server we
188+
* are connecting to.
189+
*/
190+
tmpparam = PQparameterStatus(tmpconn, "integer_datetimes");
191+
if (!tmpparam)
192+
{
193+
fprintf(stderr,
194+
_("%s: could not determine server setting for integer_datetimes\n"),
195+
progname);
196+
PQfinish(tmpconn);
197+
exit(1);
198+
}
193199

194200
#ifdef HAVE_INT64_TIMESTAMP
195-
if (strcmp(tmpparam, "on") != 0)
201+
if (strcmp(tmpparam, "on") != 0)
196202
#else
197-
if (strcmp(tmpparam, "off") != 0)
203+
if (strcmp(tmpparam, "off") != 0)
198204
#endif
199-
{
200-
fprintf(stderr,
205+
{
206+
fprintf(stderr,
201207
_("%s: integer_datetimes compile flag does not match server\n"),
202-
progname);
203-
PQfinish(tmpconn);
204-
exit(1);
205-
}
206-
207-
/* Store the password for next run */
208-
if (password)
209-
dbpassword = password;
210-
return tmpconn;
208+
progname);
209+
PQfinish(tmpconn);
210+
exit(1);
211211
}
212+
213+
return tmpconn;
212214
}

0 commit comments

Comments
 (0)