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

Commit30bf468

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 parente453cc2 commit30bf468

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

@@ -3760,7 +3821,16 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
37603821
if (strcmp(options[i].keyword,optname)==0)
37613822
{
37623823
if (options[i].val==NULL)
3824+
{
37633825
options[i].val=strdup(optval);
3826+
if (!options[i].val)
3827+
{
3828+
printfPQExpBuffer(errorMessage,
3829+
libpq_gettext("out of memory\n"));
3830+
free(result);
3831+
return3;
3832+
}
3833+
}
37643834
found_keyword= true;
37653835
break;
37663836
}
@@ -3983,6 +4053,13 @@ parseServiceFile(const char *serviceFile,
39834053
{
39844054
if (options[i].val==NULL)
39854055
options[i].val=strdup(val);
4056+
if (!options[i].val)
4057+
{
4058+
printfPQExpBuffer(errorMessage,
4059+
libpq_gettext("out of memory\n"));
4060+
fclose(f);
4061+
return3;
4062+
}
39864063
found_keyword= true;
39874064
break;
39884065
}
@@ -4402,6 +4479,14 @@ conninfo_array_parse(const char *const * keywords, const char *const * values,
44024479
if (options[k].val)
44034480
free(options[k].val);
44044481
options[k].val=strdup(str_option->val);
4482+
if (!options[k].val)
4483+
{
4484+
printfPQExpBuffer(errorMessage,
4485+
libpq_gettext("out of memory\n"));
4486+
PQconninfoFree(options);
4487+
PQconninfoFree(dbname_options);
4488+
returnNULL;
4489+
}
44054490
break;
44064491
}
44074492
}
@@ -4596,20 +4681,22 @@ conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
45964681
{
45974682
intprefix_len;
45984683
char*p;
4599-
char*buf=strdup(uri);/* need a modifiable copy of the input
4600-
* URI */
4601-
char*start=buf;
4684+
char*buf;
4685+
char*start;
46024686
charprevchar='\0';
46034687
char*user=NULL;
46044688
char*host=NULL;
46054689
boolretval= false;
46064690

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

46144701
/* Skip the URI prefix */
46154702
prefix_len=uri_prefix_length(uri);
@@ -4951,15 +5038,17 @@ conninfo_uri_parse_params(char *params,
49515038
staticchar*
49525039
conninfo_uri_decode(constchar*str,PQExpBuffererrorMessage)
49535040
{
4954-
char*buf=malloc(strlen(str)+1);
4955-
char*p=buf;
5041+
char*buf;
5042+
char*p;
49565043
constchar*q=str;
49575044

5045+
buf=malloc(strlen(str)+1);
49585046
if (buf==NULL)
49595047
{
49605048
printfPQExpBuffer(errorMessage,libpq_gettext("out of memory\n"));
49615049
returnNULL;
49625050
}
5051+
p=buf;
49635052

49645053
for (;;)
49655054
{
@@ -5104,7 +5193,6 @@ conninfo_storeval(PQconninfoOption *connOptions,
51045193
else
51055194
{
51065195
value_copy=strdup(value);
5107-
51085196
if (value_copy==NULL)
51095197
{
51105198
printfPQExpBuffer(errorMessage,libpq_gettext("out of memory\n"));
@@ -5672,6 +5760,12 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
56725760
ret=strdup(t);
56735761
fclose(fp);
56745762

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp