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

Commit5053ad2

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 parent400a4c3 commit5053ad2

File tree

1 file changed

+133
-54
lines changed

1 file changed

+133
-54
lines changed

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

Lines changed: 133 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ static intconnectDBStart(PGconn *conn);
286286
staticintconnectDBComplete(PGconn*conn);
287287
staticPGPinginternal_ping(PGconn*conn);
288288
staticPGconn*makeEmptyPGconn(void);
289-
staticvoidfillPGconn(PGconn*conn,PQconninfoOption*connOptions);
289+
staticboolfillPGconn(PGconn*conn,PQconninfoOption*connOptions);
290290
staticvoidfreePGconn(PGconn*conn);
291291
staticvoidclosePGconn(PGconn*conn);
292292
staticPQconninfoOption*conninfo_parse(constchar*conninfo,
@@ -494,7 +494,11 @@ PQconnectStartParams(const char **keywords,
494494
/*
495495
* Move option values into conn structure
496496
*/
497-
fillPGconn(conn,connOptions);
497+
if (!fillPGconn(conn,connOptions))
498+
{
499+
PQconninfoFree(connOptions);
500+
returnconn;
501+
}
498502

499503
/*
500504
* Free the option info - all is in conn now
@@ -574,7 +578,29 @@ PQconnectStart(const char *conninfo)
574578
returnconn;
575579
}
576580

577-
staticvoid
581+
/*
582+
* Move option values into conn structure
583+
*
584+
* Don't put anything cute here --- intelligence should be in
585+
* connectOptions2 ...
586+
*
587+
* Returns true on success. On failure, returns false and sets error message.
588+
*/
589+
#defineFILL_CONN_OPTION(dst,name) \
590+
do \
591+
{ \
592+
tmp = conninfo_getval(connOptions, name); \
593+
if (tmp) \
594+
{ \
595+
dst = strdup(tmp); \
596+
if (dst == NULL) \
597+
goto oom_error; \
598+
} \
599+
else \
600+
dst = NULL; \
601+
} while(0)
602+
603+
staticbool
578604
fillPGconn(PGconn*conn,PQconninfoOption*connOptions)
579605
{
580606
char*tmp;
@@ -587,48 +613,27 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
587613
*
588614
* XXX: probably worth checking strdup() return value here...
589615
*/
590-
tmp=conninfo_getval(connOptions,"hostaddr");
591-
conn->pghostaddr=tmp ?strdup(tmp) :NULL;
592-
tmp=conninfo_getval(connOptions,"host");
593-
conn->pghost=tmp ?strdup(tmp) :NULL;
594-
tmp=conninfo_getval(connOptions,"port");
595-
conn->pgport=tmp ?strdup(tmp) :NULL;
596-
tmp=conninfo_getval(connOptions,"tty");
597-
conn->pgtty=tmp ?strdup(tmp) :NULL;
598-
tmp=conninfo_getval(connOptions,"options");
599-
conn->pgoptions=tmp ?strdup(tmp) :NULL;
600-
tmp=conninfo_getval(connOptions,"application_name");
601-
conn->appname=tmp ?strdup(tmp) :NULL;
602-
tmp=conninfo_getval(connOptions,"fallback_application_name");
603-
conn->fbappname=tmp ?strdup(tmp) :NULL;
604-
tmp=conninfo_getval(connOptions,"dbname");
605-
conn->dbName=tmp ?strdup(tmp) :NULL;
606-
tmp=conninfo_getval(connOptions,"user");
607-
conn->pguser=tmp ?strdup(tmp) :NULL;
608-
tmp=conninfo_getval(connOptions,"password");
609-
conn->pgpass=tmp ?strdup(tmp) :NULL;
610-
tmp=conninfo_getval(connOptions,"connect_timeout");
611-
conn->connect_timeout=tmp ?strdup(tmp) :NULL;
612-
tmp=conninfo_getval(connOptions,"client_encoding");
613-
conn->client_encoding_initial=tmp ?strdup(tmp) :NULL;
614-
tmp=conninfo_getval(connOptions,"keepalives");
615-
conn->keepalives=tmp ?strdup(tmp) :NULL;
616-
tmp=conninfo_getval(connOptions,"keepalives_idle");
617-
conn->keepalives_idle=tmp ?strdup(tmp) :NULL;
618-
tmp=conninfo_getval(connOptions,"keepalives_interval");
619-
conn->keepalives_interval=tmp ?strdup(tmp) :NULL;
620-
tmp=conninfo_getval(connOptions,"keepalives_count");
621-
conn->keepalives_count=tmp ?strdup(tmp) :NULL;
622-
tmp=conninfo_getval(connOptions,"sslmode");
623-
conn->sslmode=tmp ?strdup(tmp) :NULL;
624-
tmp=conninfo_getval(connOptions,"sslkey");
625-
conn->sslkey=tmp ?strdup(tmp) :NULL;
626-
tmp=conninfo_getval(connOptions,"sslcert");
627-
conn->sslcert=tmp ?strdup(tmp) :NULL;
628-
tmp=conninfo_getval(connOptions,"sslrootcert");
629-
conn->sslrootcert=tmp ?strdup(tmp) :NULL;
630-
tmp=conninfo_getval(connOptions,"sslcrl");
631-
conn->sslcrl=tmp ?strdup(tmp) :NULL;
616+
FILL_CONN_OPTION(conn->pghostaddr,"hostaddr");
617+
FILL_CONN_OPTION(conn->pghost,"host");
618+
FILL_CONN_OPTION(conn->pgport,"port");
619+
FILL_CONN_OPTION(conn->pgtty,"tty");
620+
FILL_CONN_OPTION(conn->pgoptions,"options");
621+
FILL_CONN_OPTION(conn->appname,"application_name");
622+
FILL_CONN_OPTION(conn->fbappname,"fallback_application_name");
623+
FILL_CONN_OPTION(conn->dbName,"dbname");
624+
FILL_CONN_OPTION(conn->pguser,"user");
625+
FILL_CONN_OPTION(conn->pgpass,"password");
626+
FILL_CONN_OPTION(conn->connect_timeout,"connect_timeout");
627+
FILL_CONN_OPTION(conn->client_encoding_initial,"client_encoding");
628+
FILL_CONN_OPTION(conn->keepalives,"keepalives");
629+
FILL_CONN_OPTION(conn->keepalives_idle,"keepalives_idle");
630+
FILL_CONN_OPTION(conn->keepalives_interval,"keepalives_interval");
631+
FILL_CONN_OPTION(conn->keepalives_count,"keepalives_count");
632+
FILL_CONN_OPTION(conn->sslmode,"sslmode");
633+
FILL_CONN_OPTION(conn->sslkey,"sslkey");
634+
FILL_CONN_OPTION(conn->sslcert,"sslcert");
635+
FILL_CONN_OPTION(conn->sslrootcert,"sslrootcert");
636+
FILL_CONN_OPTION(conn->sslcrl,"sslcrl");
632637
#ifdefUSE_SSL
633638
tmp=conninfo_getval(connOptions,"requiressl");
634639
if (tmp&&tmp[0]=='1')
@@ -637,20 +642,25 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
637642
if (conn->sslmode)
638643
free(conn->sslmode);
639644
conn->sslmode=strdup("require");
645+
if (!conn->sslmode)
646+
return false;
640647
}
641648
#endif
642-
tmp=conninfo_getval(connOptions,"requirepeer");
643-
conn->requirepeer=tmp ?strdup(tmp) :NULL;
649+
FILL_CONN_OPTION(conn->requirepeer,"requirepeer");
644650
#if defined(KRB5)|| defined(ENABLE_GSS)|| defined(ENABLE_SSPI)
645-
tmp=conninfo_getval(connOptions,"krbsrvname");
646-
conn->krbsrvname=tmp ?strdup(tmp) :NULL;
651+
FILL_CONN_OPTION(conn->krbsrvname,"krbsrvname");
647652
#endif
648653
#if defined(ENABLE_GSS)&& defined(ENABLE_SSPI)
649-
tmp=conninfo_getval(connOptions,"gsslib");
650-
conn->gsslib=tmp ?strdup(tmp) :NULL;
654+
FILL_CONN_OPTION(conn->gsslib,"gsslib");
651655
#endif
652-
tmp=conninfo_getval(connOptions,"replication");
653-
conn->replication=tmp ?strdup(tmp) :NULL;
656+
FILL_CONN_OPTION(conn->replication,"replication");
657+
658+
return true;
659+
660+
oom_error:
661+
printfPQExpBuffer(&conn->errorMessage,
662+
libpq_gettext("out of memory\n"));
663+
return false;
654664
}
655665

656666
/*
@@ -683,7 +693,12 @@ connectOptions1(PGconn *conn, const char *conninfo)
683693
/*
684694
* Move option values into conn structure
685695
*/
686-
fillPGconn(conn,connOptions);
696+
if (!fillPGconn(conn,connOptions))
697+
{
698+
conn->status=CONNECTION_BAD;
699+
PQconninfoFree(connOptions);
700+
return false;
701+
}
687702

688703
/*
689704
* Free the option info - all is in conn now
@@ -713,6 +728,8 @@ connectOptions2(PGconn *conn)
713728
if (conn->dbName)
714729
free(conn->dbName);
715730
conn->dbName=strdup(conn->pguser);
731+
if (!conn->dbName)
732+
gotooom_error;
716733
}
717734

718735
/*
@@ -725,7 +742,12 @@ connectOptions2(PGconn *conn)
725742
conn->pgpass=PasswordFromFile(conn->pghost,conn->pgport,
726743
conn->dbName,conn->pguser);
727744
if (conn->pgpass==NULL)
745+
{
728746
conn->pgpass=strdup(DefaultPassword);
747+
if (!conn->pgpass)
748+
gotooom_error;
749+
750+
}
729751
else
730752
conn->dot_pgpass_used= true;
731753
}
@@ -783,7 +805,11 @@ connectOptions2(PGconn *conn)
783805
#endif
784806
}
785807
else
808+
{
786809
conn->sslmode=strdup(DefaultSSLMode);
810+
if (!conn->sslmode)
811+
gotooom_error;
812+
}
787813

788814
/*
789815
* Resolve special "auto" client_encoding from the locale
@@ -793,6 +819,8 @@ connectOptions2(PGconn *conn)
793819
{
794820
free(conn->client_encoding_initial);
795821
conn->client_encoding_initial=strdup(pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true)));
822+
if (!conn->client_encoding_initial)
823+
gotooom_error;
796824
}
797825

798826
/*
@@ -803,6 +831,12 @@ connectOptions2(PGconn *conn)
803831
conn->options_valid= true;
804832

805833
return true;
834+
835+
oom_error:
836+
conn->status=CONNECTION_BAD;
837+
printfPQExpBuffer(&conn->errorMessage,
838+
libpq_gettext("out of memory\n"));
839+
return false;
806840
}
807841

808842
/*
@@ -885,6 +919,8 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
885919
if (conn->dbName)
886920
free(conn->dbName);
887921
conn->dbName=strdup(dbName);
922+
if (!conn->dbName)
923+
gotooom_error;
888924
}
889925
}
890926

@@ -897,41 +933,53 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
897933
if (conn->pghost)
898934
free(conn->pghost);
899935
conn->pghost=strdup(pghost);
936+
if (!conn->pghost)
937+
gotooom_error;
900938
}
901939

902940
if (pgport&&pgport[0]!='\0')
903941
{
904942
if (conn->pgport)
905943
free(conn->pgport);
906944
conn->pgport=strdup(pgport);
945+
if (!conn->pgport)
946+
gotooom_error;
907947
}
908948

909949
if (pgoptions&&pgoptions[0]!='\0')
910950
{
911951
if (conn->pgoptions)
912952
free(conn->pgoptions);
913953
conn->pgoptions=strdup(pgoptions);
954+
if (!conn->pgoptions)
955+
gotooom_error;
914956
}
915957

916958
if (pgtty&&pgtty[0]!='\0')
917959
{
918960
if (conn->pgtty)
919961
free(conn->pgtty);
920962
conn->pgtty=strdup(pgtty);
963+
if (!conn->pgtty)
964+
gotooom_error;
921965
}
922966

923967
if (login&&login[0]!='\0')
924968
{
925969
if (conn->pguser)
926970
free(conn->pguser);
927971
conn->pguser=strdup(login);
972+
if (!conn->pguser)
973+
gotooom_error;
928974
}
929975

930976
if (pwd&&pwd[0]!='\0')
931977
{
932978
if (conn->pgpass)
933979
free(conn->pgpass);
934980
conn->pgpass=strdup(pwd);
981+
if (!conn->pgpass)
982+
gotooom_error;
935983
}
936984

937985
/*
@@ -947,6 +995,12 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
947995
(void)connectDBComplete(conn);
948996

949997
returnconn;
998+
999+
oom_error:
1000+
conn->status=CONNECTION_BAD;
1001+
printfPQExpBuffer(&conn->errorMessage,
1002+
libpq_gettext("out of memory\n"));
1003+
returnconn;
9501004
}
9511005

9521006

@@ -3761,7 +3815,16 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
37613815
if (strcmp(options[i].keyword,optname)==0)
37623816
{
37633817
if (options[i].val==NULL)
3818+
{
37643819
options[i].val=strdup(optval);
3820+
if (!options[i].val)
3821+
{
3822+
printfPQExpBuffer(errorMessage,
3823+
libpq_gettext("out of memory\n"));
3824+
free(result);
3825+
return3;
3826+
}
3827+
}
37653828
found_keyword= true;
37663829
break;
37673830
}
@@ -3984,6 +4047,13 @@ parseServiceFile(const char *serviceFile,
39844047
{
39854048
if (options[i].val==NULL)
39864049
options[i].val=strdup(val);
4050+
if (!options[i].val)
4051+
{
4052+
printfPQExpBuffer(errorMessage,
4053+
libpq_gettext("out of memory\n"));
4054+
fclose(f);
4055+
return3;
4056+
}
39874057
found_keyword= true;
39884058
break;
39894059
}
@@ -4411,6 +4481,14 @@ conninfo_array_parse(const char **keywords, const char **values,
44114481
if (options[k].val)
44124482
free(options[k].val);
44134483
options[k].val=strdup(str_option->val);
4484+
if (!options[k].val)
4485+
{
4486+
printfPQExpBuffer(errorMessage,
4487+
libpq_gettext("out of memory\n"));
4488+
PQconninfoFree(options);
4489+
PQconninfoFree(str_options);
4490+
returnNULL;
4491+
}
44144492
break;
44154493
}
44164494
}
@@ -4430,6 +4508,7 @@ conninfo_array_parse(const char **keywords, const char **values,
44304508
printfPQExpBuffer(errorMessage,
44314509
libpq_gettext("out of memory\n"));
44324510
PQconninfoFree(options);
4511+
PQconninfoFree(str_options);
44334512
returnNULL;
44344513
}
44354514
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp