Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit811015f

Browse files
committed
Check return value of strdup() in libpq connection option parsing.
An out-of-memory in most of these would lead to strange behavior, likeconnecting to a different database than intended, but some would lead toan outright segfault.Alex Shulgin and me. Backpatch to all supported versions.
1 parent3852eab commit811015f

File tree

1 file changed

+113
-19
lines changed

1 file changed

+113
-19
lines changed

‎src/interfaces/libpq/fe-connect.c

Lines changed: 113 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ static intconnectDBStart(PGconn *conn);
333333
staticintconnectDBComplete(PGconn*conn);
334334
staticPGPinginternal_ping(PGconn*conn);
335335
staticPGconn*makeEmptyPGconn(void);
336-
staticvoidfillPGconn(PGconn*conn,PQconninfoOption*connOptions);
336+
staticboolfillPGconn(PGconn*conn,PQconninfoOption*connOptions);
337337
staticvoidfreePGconn(PGconn*conn);
338338
staticvoidclosePGconn(PGconn*conn);
339339
staticPQconninfoOption*conninfo_init(PQExpBuffererrorMessage);
@@ -585,7 +585,11 @@ PQconnectStartParams(const char *const * keywords,
585585
/*
586586
* Move option values into conn structure
587587
*/
588-
fillPGconn(conn,connOptions);
588+
if (!fillPGconn(conn,connOptions))
589+
{
590+
PQconninfoFree(connOptions);
591+
returnconn;
592+
}
589593

590594
/*
591595
* Free the option info - all is in conn now
@@ -665,19 +669,19 @@ PQconnectStart(const char *conninfo)
665669
returnconn;
666670
}
667671

668-
staticvoid
672+
/*
673+
* Move option values into conn structure
674+
*
675+
* Don't put anything cute here --- intelligence should be in
676+
* connectOptions2 ...
677+
*
678+
* Returns true on success. On failure, returns false and sets error message.
679+
*/
680+
staticbool
669681
fillPGconn(PGconn*conn,PQconninfoOption*connOptions)
670682
{
671683
constinternalPQconninfoOption*option;
672684

673-
/*
674-
* Move option values into conn structure
675-
*
676-
* Don't put anything cute here --- intelligence should be in
677-
* connectOptions2 ...
678-
*
679-
* XXX: probably worth checking strdup() return value here...
680-
*/
681685
for (option=PQconninfoOptions;option->keyword;option++)
682686
{
683687
constchar*tmp=conninfo_getval(connOptions,option->keyword);
@@ -688,9 +692,22 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
688692

689693
if (*connmember)
690694
free(*connmember);
691-
*connmember=tmp ?strdup(tmp) :NULL;
695+
if (tmp)
696+
{
697+
*connmember=strdup(tmp);
698+
if (*connmember==NULL)
699+
{
700+
printfPQExpBuffer(&conn->errorMessage,
701+
libpq_gettext("out of memory\n"));
702+
return false;
703+
}
704+
}
705+
else
706+
*connmember=NULL;
692707
}
693708
}
709+
710+
return true;
694711
}
695712

696713
/*
@@ -723,7 +740,12 @@ connectOptions1(PGconn *conn, const char *conninfo)
723740
/*
724741
* Move option values into conn structure
725742
*/
726-
fillPGconn(conn,connOptions);
743+
if (!fillPGconn(conn,connOptions))
744+
{
745+
conn->status=CONNECTION_BAD;
746+
PQconninfoFree(connOptions);
747+
return false;
748+
}
727749

728750
/*
729751
* Free the option info - all is in conn now
@@ -753,6 +775,8 @@ connectOptions2(PGconn *conn)
753775
if (conn->dbName)
754776
free(conn->dbName);
755777
conn->dbName=strdup(conn->pguser);
778+
if (!conn->dbName)
779+
gotooom_error;
756780
}
757781

758782
/*
@@ -765,7 +789,12 @@ connectOptions2(PGconn *conn)
765789
conn->pgpass=PasswordFromFile(conn->pghost,conn->pgport,
766790
conn->dbName,conn->pguser);
767791
if (conn->pgpass==NULL)
792+
{
768793
conn->pgpass=strdup(DefaultPassword);
794+
if (!conn->pgpass)
795+
gotooom_error;
796+
797+
}
769798
else
770799
conn->dot_pgpass_used= true;
771800
}
@@ -823,7 +852,11 @@ connectOptions2(PGconn *conn)
823852
#endif
824853
}
825854
else
855+
{
826856
conn->sslmode=strdup(DefaultSSLMode);
857+
if (!conn->sslmode)
858+
gotooom_error;
859+
}
827860

828861
/*
829862
* Resolve special "auto" client_encoding from the locale
@@ -833,6 +866,8 @@ connectOptions2(PGconn *conn)
833866
{
834867
free(conn->client_encoding_initial);
835868
conn->client_encoding_initial=strdup(pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true)));
869+
if (!conn->client_encoding_initial)
870+
gotooom_error;
836871
}
837872

838873
/*
@@ -843,6 +878,12 @@ connectOptions2(PGconn *conn)
843878
conn->options_valid= true;
844879

845880
return true;
881+
882+
oom_error:
883+
conn->status=CONNECTION_BAD;
884+
printfPQExpBuffer(&conn->errorMessage,
885+
libpq_gettext("out of memory\n"));
886+
return false;
846887
}
847888

848889
/*
@@ -937,6 +978,8 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
937978
if (conn->dbName)
938979
free(conn->dbName);
939980
conn->dbName=strdup(dbName);
981+
if (!conn->dbName)
982+
gotooom_error;
940983
}
941984
}
942985

@@ -949,41 +992,53 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
949992
if (conn->pghost)
950993
free(conn->pghost);
951994
conn->pghost=strdup(pghost);
995+
if (!conn->pghost)
996+
gotooom_error;
952997
}
953998

954999
if (pgport&&pgport[0]!='\0')
9551000
{
9561001
if (conn->pgport)
9571002
free(conn->pgport);
9581003
conn->pgport=strdup(pgport);
1004+
if (!conn->pgport)
1005+
gotooom_error;
9591006
}
9601007

9611008
if (pgoptions&&pgoptions[0]!='\0')
9621009
{
9631010
if (conn->pgoptions)
9641011
free(conn->pgoptions);
9651012
conn->pgoptions=strdup(pgoptions);
1013+
if (!conn->pgoptions)
1014+
gotooom_error;
9661015
}
9671016

9681017
if (pgtty&&pgtty[0]!='\0')
9691018
{
9701019
if (conn->pgtty)
9711020
free(conn->pgtty);
9721021
conn->pgtty=strdup(pgtty);
1022+
if (!conn->pgtty)
1023+
gotooom_error;
9731024
}
9741025

9751026
if (login&&login[0]!='\0')
9761027
{
9771028
if (conn->pguser)
9781029
free(conn->pguser);
9791030
conn->pguser=strdup(login);
1031+
if (!conn->pguser)
1032+
gotooom_error;
9801033
}
9811034

9821035
if (pwd&&pwd[0]!='\0')
9831036
{
9841037
if (conn->pgpass)
9851038
free(conn->pgpass);
9861039
conn->pgpass=strdup(pwd);
1040+
if (!conn->pgpass)
1041+
gotooom_error;
9871042
}
9881043

9891044
/*
@@ -999,6 +1054,12 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
9991054
(void)connectDBComplete(conn);
10001055

10011056
returnconn;
1057+
1058+
oom_error:
1059+
conn->status=CONNECTION_BAD;
1060+
printfPQExpBuffer(&conn->errorMessage,
1061+
libpq_gettext("out of memory\n"));
1062+
returnconn;
10021063
}
10031064

10041065

@@ -3759,7 +3820,16 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
37593820
if (strcmp(options[i].keyword,optname)==0)
37603821
{
37613822
if (options[i].val==NULL)
3823+
{
37623824
options[i].val=strdup(optval);
3825+
if (!options[i].val)
3826+
{
3827+
printfPQExpBuffer(errorMessage,
3828+
libpq_gettext("out of memory\n"));
3829+
free(result);
3830+
return3;
3831+
}
3832+
}
37633833
found_keyword= true;
37643834
break;
37653835
}
@@ -3982,6 +4052,13 @@ parseServiceFile(const char *serviceFile,
39824052
{
39834053
if (options[i].val==NULL)
39844054
options[i].val=strdup(val);
4055+
if (!options[i].val)
4056+
{
4057+
printfPQExpBuffer(errorMessage,
4058+
libpq_gettext("out of memory\n"));
4059+
fclose(f);
4060+
return3;
4061+
}
39854062
found_keyword= true;
39864063
break;
39874064
}
@@ -4401,6 +4478,14 @@ conninfo_array_parse(const char *const * keywords, const char *const * values,
44014478
if (options[k].val)
44024479
free(options[k].val);
44034480
options[k].val=strdup(str_option->val);
4481+
if (!options[k].val)
4482+
{
4483+
printfPQExpBuffer(errorMessage,
4484+
libpq_gettext("out of memory\n"));
4485+
PQconninfoFree(options);
4486+
PQconninfoFree(dbname_options);
4487+
returnNULL;
4488+
}
44044489
break;
44054490
}
44064491
}
@@ -4595,20 +4680,22 @@ conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
45954680
{
45964681
intprefix_len;
45974682
char*p;
4598-
char*buf=strdup(uri);/* need a modifiable copy of the input
4599-
* URI */
4600-
char*start=buf;
4683+
char*buf;
4684+
char*start;
46014685
charprevchar='\0';
46024686
char*user=NULL;
46034687
char*host=NULL;
46044688
boolretval= false;
46054689

4690+
/* need a modifiable copy of the input URI */
4691+
buf=strdup(uri);
46064692
if (buf==NULL)
46074693
{
46084694
printfPQExpBuffer(errorMessage,
46094695
libpq_gettext("out of memory\n"));
46104696
return false;
46114697
}
4698+
start=buf;
46124699

46134700
/* Skip the URI prefix */
46144701
prefix_len=uri_prefix_length(uri);
@@ -4950,15 +5037,17 @@ conninfo_uri_parse_params(char *params,
49505037
staticchar*
49515038
conninfo_uri_decode(constchar*str,PQExpBuffererrorMessage)
49525039
{
4953-
char*buf=malloc(strlen(str)+1);
4954-
char*p=buf;
5040+
char*buf;
5041+
char*p;
49555042
constchar*q=str;
49565043

5044+
buf=malloc(strlen(str)+1);
49575045
if (buf==NULL)
49585046
{
49595047
printfPQExpBuffer(errorMessage,libpq_gettext("out of memory\n"));
49605048
returnNULL;
49615049
}
5050+
p=buf;
49625051

49635052
for (;;)
49645053
{
@@ -5103,7 +5192,6 @@ conninfo_storeval(PQconninfoOption *connOptions,
51035192
else
51045193
{
51055194
value_copy=strdup(value);
5106-
51075195
if (value_copy==NULL)
51085196
{
51095197
printfPQExpBuffer(errorMessage,libpq_gettext("out of memory\n"));
@@ -5671,6 +5759,12 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
56715759
ret=strdup(t);
56725760
fclose(fp);
56735761

5762+
if (!ret)
5763+
{
5764+
/* Out of memory. XXX: an error message would be nice. */
5765+
returnNULL;
5766+
}
5767+
56745768
/* De-escape password. */
56755769
for (p1=p2=ret;*p1!=':'&&*p1!='\0';++p1,++p2)
56765770
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp