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

Commit1f35170

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 parentd2e00c3 commit1f35170

File tree

1 file changed

+129
-58
lines changed

1 file changed

+129
-58
lines changed

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

Lines changed: 129 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ static bool connectOptions2(PGconn *conn);
280280
staticintconnectDBStart(PGconn*conn);
281281
staticintconnectDBComplete(PGconn*conn);
282282
staticPGconn*makeEmptyPGconn(void);
283-
staticvoidfillPGconn(PGconn*conn,PQconninfoOption*connOptions);
283+
staticboolfillPGconn(PGconn*conn,PQconninfoOption*connOptions);
284284
staticvoidfreePGconn(PGconn*conn);
285285
staticvoidclosePGconn(PGconn*conn);
286286
staticPQconninfoOption*conninfo_parse(constchar*conninfo,
@@ -452,7 +452,11 @@ PQconnectStartParams(const char **keywords,
452452
/*
453453
* Move option values into conn structure
454454
*/
455-
fillPGconn(conn,connOptions);
455+
if (!fillPGconn(conn,connOptions))
456+
{
457+
PQconninfoFree(connOptions);
458+
returnconn;
459+
}
456460

457461
/*
458462
* Free the option info - all is in conn now
@@ -532,59 +536,53 @@ PQconnectStart(const char *conninfo)
532536
returnconn;
533537
}
534538

535-
staticvoid
539+
/*
540+
* Move option values into conn structure
541+
*
542+
* Don't put anything cute here --- intelligence should be in
543+
* connectOptions2 ...
544+
*
545+
* Returns true on success. On failure, returns false and sets error message.
546+
*/
547+
#defineFILL_CONN_OPTION(dst,name) \
548+
do \
549+
{ \
550+
tmp = conninfo_getval(connOptions, name); \
551+
if (tmp) \
552+
{ \
553+
dst = strdup(tmp); \
554+
if (dst == NULL) \
555+
goto oom_error; \
556+
} \
557+
else \
558+
dst = NULL; \
559+
} while(0)
560+
561+
staticbool
536562
fillPGconn(PGconn*conn,PQconninfoOption*connOptions)
537563
{
538564
char*tmp;
539565

540-
/*
541-
* Move option values into conn structure
542-
*
543-
* Don't put anything cute here --- intelligence should be in
544-
* connectOptions2 ...
545-
*
546-
* XXX: probably worth checking strdup() return value here...
547-
*/
548-
tmp=conninfo_getval(connOptions,"hostaddr");
549-
conn->pghostaddr=tmp ?strdup(tmp) :NULL;
550-
tmp=conninfo_getval(connOptions,"host");
551-
conn->pghost=tmp ?strdup(tmp) :NULL;
552-
tmp=conninfo_getval(connOptions,"port");
553-
conn->pgport=tmp ?strdup(tmp) :NULL;
554-
tmp=conninfo_getval(connOptions,"tty");
555-
conn->pgtty=tmp ?strdup(tmp) :NULL;
556-
tmp=conninfo_getval(connOptions,"options");
557-
conn->pgoptions=tmp ?strdup(tmp) :NULL;
558-
tmp=conninfo_getval(connOptions,"application_name");
559-
conn->appname=tmp ?strdup(tmp) :NULL;
560-
tmp=conninfo_getval(connOptions,"fallback_application_name");
561-
conn->fbappname=tmp ?strdup(tmp) :NULL;
562-
tmp=conninfo_getval(connOptions,"dbname");
563-
conn->dbName=tmp ?strdup(tmp) :NULL;
564-
tmp=conninfo_getval(connOptions,"user");
565-
conn->pguser=tmp ?strdup(tmp) :NULL;
566-
tmp=conninfo_getval(connOptions,"password");
567-
conn->pgpass=tmp ?strdup(tmp) :NULL;
568-
tmp=conninfo_getval(connOptions,"connect_timeout");
569-
conn->connect_timeout=tmp ?strdup(tmp) :NULL;
570-
tmp=conninfo_getval(connOptions,"keepalives");
571-
conn->keepalives=tmp ?strdup(tmp) :NULL;
572-
tmp=conninfo_getval(connOptions,"keepalives_idle");
573-
conn->keepalives_idle=tmp ?strdup(tmp) :NULL;
574-
tmp=conninfo_getval(connOptions,"keepalives_interval");
575-
conn->keepalives_interval=tmp ?strdup(tmp) :NULL;
576-
tmp=conninfo_getval(connOptions,"keepalives_count");
577-
conn->keepalives_count=tmp ?strdup(tmp) :NULL;
578-
tmp=conninfo_getval(connOptions,"sslmode");
579-
conn->sslmode=tmp ?strdup(tmp) :NULL;
580-
tmp=conninfo_getval(connOptions,"sslkey");
581-
conn->sslkey=tmp ?strdup(tmp) :NULL;
582-
tmp=conninfo_getval(connOptions,"sslcert");
583-
conn->sslcert=tmp ?strdup(tmp) :NULL;
584-
tmp=conninfo_getval(connOptions,"sslrootcert");
585-
conn->sslrootcert=tmp ?strdup(tmp) :NULL;
586-
tmp=conninfo_getval(connOptions,"sslcrl");
587-
conn->sslcrl=tmp ?strdup(tmp) :NULL;
566+
FILL_CONN_OPTION(conn->pghostaddr,"hostaddr");
567+
FILL_CONN_OPTION(conn->pghost,"host");
568+
FILL_CONN_OPTION(conn->pgport,"port");
569+
FILL_CONN_OPTION(conn->pgtty,"tty");
570+
FILL_CONN_OPTION(conn->pgoptions,"options");
571+
FILL_CONN_OPTION(conn->appname,"application_name");
572+
FILL_CONN_OPTION(conn->fbappname,"fallback_application_name");
573+
FILL_CONN_OPTION(conn->dbName,"dbname");
574+
FILL_CONN_OPTION(conn->pguser,"user");
575+
FILL_CONN_OPTION(conn->pgpass,"password");
576+
FILL_CONN_OPTION(conn->connect_timeout,"connect_timeout");
577+
FILL_CONN_OPTION(conn->keepalives,"keepalives");
578+
FILL_CONN_OPTION(conn->keepalives_idle,"keepalives_idle");
579+
FILL_CONN_OPTION(conn->keepalives_interval,"keepalives_interval");
580+
FILL_CONN_OPTION(conn->keepalives_count,"keepalives_count");
581+
FILL_CONN_OPTION(conn->sslmode,"sslmode");
582+
FILL_CONN_OPTION(conn->sslkey,"sslkey");
583+
FILL_CONN_OPTION(conn->sslcert,"sslcert");
584+
FILL_CONN_OPTION(conn->sslrootcert,"sslrootcert");
585+
FILL_CONN_OPTION(conn->sslcrl,"sslcrl");
588586
#ifdefUSE_SSL
589587
tmp=conninfo_getval(connOptions,"requiressl");
590588
if (tmp&&tmp[0]=='1')
@@ -593,18 +591,24 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
593591
if (conn->sslmode)
594592
free(conn->sslmode);
595593
conn->sslmode=strdup("require");
594+
if (!conn->sslmode)
595+
return false;
596596
}
597597
#endif
598598
#if defined(KRB5)|| defined(ENABLE_GSS)|| defined(ENABLE_SSPI)
599-
tmp=conninfo_getval(connOptions,"krbsrvname");
600-
conn->krbsrvname=tmp ?strdup(tmp) :NULL;
599+
FILL_CONN_OPTION(conn->krbsrvname,"krbsrvname");
601600
#endif
602601
#if defined(ENABLE_GSS)&& defined(ENABLE_SSPI)
603-
tmp=conninfo_getval(connOptions,"gsslib");
604-
conn->gsslib=tmp ?strdup(tmp) :NULL;
602+
FILL_CONN_OPTION(conn->gsslib,"gsslib");
605603
#endif
606-
tmp=conninfo_getval(connOptions,"replication");
607-
conn->replication=tmp ?strdup(tmp) :NULL;
604+
FILL_CONN_OPTION(conn->replication,"replication");
605+
606+
return true;
607+
608+
oom_error:
609+
printfPQExpBuffer(&conn->errorMessage,
610+
libpq_gettext("out of memory\n"));
611+
return false;
608612
}
609613

610614
/*
@@ -637,7 +641,12 @@ connectOptions1(PGconn *conn, const char *conninfo)
637641
/*
638642
* Move option values into conn structure
639643
*/
640-
fillPGconn(conn,connOptions);
644+
if (!fillPGconn(conn,connOptions))
645+
{
646+
conn->status=CONNECTION_BAD;
647+
PQconninfoFree(connOptions);
648+
return false;
649+
}
641650

642651
/*
643652
* Free the option info - all is in conn now
@@ -667,6 +676,8 @@ connectOptions2(PGconn *conn)
667676
if (conn->dbName)
668677
free(conn->dbName);
669678
conn->dbName=strdup(conn->pguser);
679+
if (!conn->dbName)
680+
gotooom_error;
670681
}
671682

672683
/*
@@ -679,7 +690,12 @@ connectOptions2(PGconn *conn)
679690
conn->pgpass=PasswordFromFile(conn->pghost,conn->pgport,
680691
conn->dbName,conn->pguser);
681692
if (conn->pgpass==NULL)
693+
{
682694
conn->pgpass=strdup(DefaultPassword);
695+
if (!conn->pgpass)
696+
gotooom_error;
697+
698+
}
683699
else
684700
conn->dot_pgpass_used= true;
685701
}
@@ -737,7 +753,11 @@ connectOptions2(PGconn *conn)
737753
#endif
738754
}
739755
else
756+
{
740757
conn->sslmode=strdup(DefaultSSLMode);
758+
if (!conn->sslmode)
759+
gotooom_error;
760+
}
741761

742762
/*
743763
* Only if we get this far is it appropriate to try to connect. (We need a
@@ -747,6 +767,12 @@ connectOptions2(PGconn *conn)
747767
conn->options_valid= true;
748768

749769
return true;
770+
771+
oom_error:
772+
conn->status=CONNECTION_BAD;
773+
printfPQExpBuffer(&conn->errorMessage,
774+
libpq_gettext("out of memory\n"));
775+
return false;
750776
}
751777

752778
/*
@@ -829,6 +855,8 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
829855
if (conn->dbName)
830856
free(conn->dbName);
831857
conn->dbName=strdup(dbName);
858+
if (!conn->dbName)
859+
gotooom_error;
832860
}
833861
}
834862

@@ -841,41 +869,53 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
841869
if (conn->pghost)
842870
free(conn->pghost);
843871
conn->pghost=strdup(pghost);
872+
if (!conn->pghost)
873+
gotooom_error;
844874
}
845875

846876
if (pgport&&pgport[0]!='\0')
847877
{
848878
if (conn->pgport)
849879
free(conn->pgport);
850880
conn->pgport=strdup(pgport);
881+
if (!conn->pgport)
882+
gotooom_error;
851883
}
852884

853885
if (pgoptions&&pgoptions[0]!='\0')
854886
{
855887
if (conn->pgoptions)
856888
free(conn->pgoptions);
857889
conn->pgoptions=strdup(pgoptions);
890+
if (!conn->pgoptions)
891+
gotooom_error;
858892
}
859893

860894
if (pgtty&&pgtty[0]!='\0')
861895
{
862896
if (conn->pgtty)
863897
free(conn->pgtty);
864898
conn->pgtty=strdup(pgtty);
899+
if (!conn->pgtty)
900+
gotooom_error;
865901
}
866902

867903
if (login&&login[0]!='\0')
868904
{
869905
if (conn->pguser)
870906
free(conn->pguser);
871907
conn->pguser=strdup(login);
908+
if (!conn->pguser)
909+
gotooom_error;
872910
}
873911

874912
if (pwd&&pwd[0]!='\0')
875913
{
876914
if (conn->pgpass)
877915
free(conn->pgpass);
878916
conn->pgpass=strdup(pwd);
917+
if (!conn->pgpass)
918+
gotooom_error;
879919
}
880920

881921
/*
@@ -891,6 +931,12 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
891931
(void)connectDBComplete(conn);
892932

893933
returnconn;
934+
935+
oom_error:
936+
conn->status=CONNECTION_BAD;
937+
printfPQExpBuffer(&conn->errorMessage,
938+
libpq_gettext("out of memory\n"));
939+
returnconn;
894940
}
895941

896942

@@ -3530,7 +3576,16 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
35303576
if (strcmp(options[i].keyword,optname)==0)
35313577
{
35323578
if (options[i].val==NULL)
3579+
{
35333580
options[i].val=strdup(optval);
3581+
if (!options[i].val)
3582+
{
3583+
printfPQExpBuffer(errorMessage,
3584+
libpq_gettext("out of memory\n"));
3585+
free(result);
3586+
return3;
3587+
}
3588+
}
35343589
found_keyword= true;
35353590
break;
35363591
}
@@ -3753,6 +3808,13 @@ parseServiceFile(const char *serviceFile,
37533808
{
37543809
if (options[i].val==NULL)
37553810
options[i].val=strdup(val);
3811+
if (!options[i].val)
3812+
{
3813+
printfPQExpBuffer(errorMessage,
3814+
libpq_gettext("out of memory\n"));
3815+
fclose(f);
3816+
return3;
3817+
}
37563818
found_keyword= true;
37573819
break;
37583820
}
@@ -4180,6 +4242,14 @@ conninfo_array_parse(const char **keywords, const char **values,
41804242
if (options[k].val)
41814243
free(options[k].val);
41824244
options[k].val=strdup(str_option->val);
4245+
if (!options[k].val)
4246+
{
4247+
printfPQExpBuffer(errorMessage,
4248+
libpq_gettext("out of memory\n"));
4249+
PQconninfoFree(options);
4250+
PQconninfoFree(str_options);
4251+
returnNULL;
4252+
}
41834253
break;
41844254
}
41854255
}
@@ -4199,6 +4269,7 @@ conninfo_array_parse(const char **keywords, const char **values,
41994269
printfPQExpBuffer(errorMessage,
42004270
libpq_gettext("out of memory\n"));
42014271
PQconninfoFree(options);
4272+
PQconninfoFree(str_options);
42024273
returnNULL;
42034274
}
42044275
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp