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

Commitd3b162a

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 parentc57cdc9 commitd3b162a

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
/*
@@ -936,6 +977,8 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
936977
if (conn->dbName)
937978
free(conn->dbName);
938979
conn->dbName=strdup(dbName);
980+
if (!conn->dbName)
981+
gotooom_error;
939982
}
940983
}
941984

@@ -948,41 +991,53 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
948991
if (conn->pghost)
949992
free(conn->pghost);
950993
conn->pghost=strdup(pghost);
994+
if (!conn->pghost)
995+
gotooom_error;
951996
}
952997

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

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

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

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

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

9881043
/*
@@ -998,6 +1053,12 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
9981053
(void)connectDBComplete(conn);
9991054

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

10031064

@@ -3774,7 +3835,16 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
37743835
if (strcmp(options[i].keyword,optname)==0)
37753836
{
37763837
if (options[i].val==NULL)
3838+
{
37773839
options[i].val=strdup(optval);
3840+
if (!options[i].val)
3841+
{
3842+
printfPQExpBuffer(errorMessage,
3843+
libpq_gettext("out of memory\n"));
3844+
free(result);
3845+
return3;
3846+
}
3847+
}
37783848
found_keyword= true;
37793849
break;
37803850
}
@@ -3997,6 +4067,13 @@ parseServiceFile(const char *serviceFile,
39974067
{
39984068
if (options[i].val==NULL)
39994069
options[i].val=strdup(val);
4070+
if (!options[i].val)
4071+
{
4072+
printfPQExpBuffer(errorMessage,
4073+
libpq_gettext("out of memory\n"));
4074+
fclose(f);
4075+
return3;
4076+
}
40004077
found_keyword= true;
40014078
break;
40024079
}
@@ -4416,6 +4493,14 @@ conninfo_array_parse(const char *const * keywords, const char *const * values,
44164493
if (options[k].val)
44174494
free(options[k].val);
44184495
options[k].val=strdup(str_option->val);
4496+
if (!options[k].val)
4497+
{
4498+
printfPQExpBuffer(errorMessage,
4499+
libpq_gettext("out of memory\n"));
4500+
PQconninfoFree(options);
4501+
PQconninfoFree(dbname_options);
4502+
returnNULL;
4503+
}
44194504
break;
44204505
}
44214506
}
@@ -4599,20 +4684,22 @@ conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
45994684
{
46004685
intprefix_len;
46014686
char*p;
4602-
char*buf=strdup(uri);/* need a modifiable copy of the input
4603-
* URI */
4604-
char*start=buf;
4687+
char*buf;
4688+
char*start;
46054689
charprevchar='\0';
46064690
char*user=NULL;
46074691
char*host=NULL;
46084692
boolretval= false;
46094693

4694+
/* need a modifiable copy of the input URI */
4695+
buf=strdup(uri);
46104696
if (buf==NULL)
46114697
{
46124698
printfPQExpBuffer(errorMessage,
46134699
libpq_gettext("out of memory\n"));
46144700
return false;
46154701
}
4702+
start=buf;
46164703

46174704
/* Skip the URI prefix */
46184705
prefix_len=uri_prefix_length(uri);
@@ -4954,15 +5041,17 @@ conninfo_uri_parse_params(char *params,
49545041
staticchar*
49555042
conninfo_uri_decode(constchar*str,PQExpBuffererrorMessage)
49565043
{
4957-
char*buf=malloc(strlen(str)+1);
4958-
char*p=buf;
5044+
char*buf;
5045+
char*p;
49595046
constchar*q=str;
49605047

5048+
buf=malloc(strlen(str)+1);
49615049
if (buf==NULL)
49625050
{
49635051
printfPQExpBuffer(errorMessage,libpq_gettext("out of memory\n"));
49645052
returnNULL;
49655053
}
5054+
p=buf;
49665055

49675056
for (;;)
49685057
{
@@ -5107,7 +5196,6 @@ conninfo_storeval(PQconninfoOption *connOptions,
51075196
else
51085197
{
51095198
value_copy=strdup(value);
5110-
51115199
if (value_copy==NULL)
51125200
{
51135201
printfPQExpBuffer(errorMessage,libpq_gettext("out of memory\n"));
@@ -5667,6 +5755,12 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
56675755
ret=strdup(t);
56685756
fclose(fp);
56695757

5758+
if (!ret)
5759+
{
5760+
/* Out of memory. XXX: an error message would be nice. */
5761+
returnNULL;
5762+
}
5763+
56705764
/* De-escape password. */
56715765
for (p1=p2=ret;*p1!=':'&&*p1!='\0';++p1,++p2)
56725766
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp