@@ -333,7 +333,7 @@ static int connectDBStart(PGconn *conn);
333
333
static int connectDBComplete(PGconn *conn);
334
334
static PGPing internal_ping(PGconn *conn);
335
335
static PGconn *makeEmptyPGconn(void);
336
- static void fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
336
+ static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
337
337
static void freePGconn(PGconn *conn);
338
338
static void closePGconn(PGconn *conn);
339
339
static PQconninfoOption *conninfo_init(PQExpBuffer errorMessage);
@@ -585,7 +585,11 @@ PQconnectStartParams(const char *const * keywords,
585
585
/*
586
586
* Move option values into conn structure
587
587
*/
588
- fillPGconn(conn, connOptions);
588
+ if (!fillPGconn(conn, connOptions))
589
+ {
590
+ PQconninfoFree(connOptions);
591
+ return conn;
592
+ }
589
593
590
594
/*
591
595
* Free the option info - all is in conn now
@@ -665,19 +669,19 @@ PQconnectStart(const char *conninfo)
665
669
return conn;
666
670
}
667
671
668
- static void
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
+ static bool
669
681
fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
670
682
{
671
683
const internalPQconninfoOption *option;
672
684
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
- */
681
685
for (option = PQconninfoOptions; option->keyword; option++)
682
686
{
683
687
const char *tmp = conninfo_getval(connOptions, option->keyword);
@@ -688,9 +692,22 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
688
692
689
693
if (*connmember)
690
694
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;
692
707
}
693
708
}
709
+
710
+ return true;
694
711
}
695
712
696
713
/*
@@ -723,7 +740,12 @@ connectOptions1(PGconn *conn, const char *conninfo)
723
740
/*
724
741
* Move option values into conn structure
725
742
*/
726
- fillPGconn(conn, connOptions);
743
+ if (!fillPGconn(conn, connOptions))
744
+ {
745
+ conn->status = CONNECTION_BAD;
746
+ PQconninfoFree(connOptions);
747
+ return false;
748
+ }
727
749
728
750
/*
729
751
* Free the option info - all is in conn now
@@ -753,6 +775,8 @@ connectOptions2(PGconn *conn)
753
775
if (conn->dbName)
754
776
free(conn->dbName);
755
777
conn->dbName = strdup(conn->pguser);
778
+ if (!conn->dbName)
779
+ goto oom_error;
756
780
}
757
781
758
782
/*
@@ -765,7 +789,12 @@ connectOptions2(PGconn *conn)
765
789
conn->pgpass = PasswordFromFile(conn->pghost, conn->pgport,
766
790
conn->dbName, conn->pguser);
767
791
if (conn->pgpass == NULL)
792
+ {
768
793
conn->pgpass = strdup(DefaultPassword);
794
+ if (!conn->pgpass)
795
+ goto oom_error;
796
+
797
+ }
769
798
else
770
799
conn->dot_pgpass_used = true;
771
800
}
@@ -823,7 +852,11 @@ connectOptions2(PGconn *conn)
823
852
#endif
824
853
}
825
854
else
855
+ {
826
856
conn->sslmode = strdup(DefaultSSLMode);
857
+ if (!conn->sslmode)
858
+ goto oom_error;
859
+ }
827
860
828
861
/*
829
862
* Resolve special "auto" client_encoding from the locale
@@ -833,6 +866,8 @@ connectOptions2(PGconn *conn)
833
866
{
834
867
free(conn->client_encoding_initial);
835
868
conn->client_encoding_initial = strdup(pg_encoding_to_char(pg_get_encoding_from_locale(NULL, true)));
869
+ if (!conn->client_encoding_initial)
870
+ goto oom_error;
836
871
}
837
872
838
873
/*
@@ -843,6 +878,12 @@ connectOptions2(PGconn *conn)
843
878
conn->options_valid = true;
844
879
845
880
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;
846
887
}
847
888
848
889
/*
@@ -937,6 +978,8 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
937
978
if (conn->dbName)
938
979
free(conn->dbName);
939
980
conn->dbName = strdup(dbName);
981
+ if (!conn->dbName)
982
+ goto oom_error;
940
983
}
941
984
}
942
985
@@ -949,41 +992,53 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
949
992
if (conn->pghost)
950
993
free(conn->pghost);
951
994
conn->pghost = strdup(pghost);
995
+ if (!conn->pghost)
996
+ goto oom_error;
952
997
}
953
998
954
999
if (pgport && pgport[0] != '\0')
955
1000
{
956
1001
if (conn->pgport)
957
1002
free(conn->pgport);
958
1003
conn->pgport = strdup(pgport);
1004
+ if (!conn->pgport)
1005
+ goto oom_error;
959
1006
}
960
1007
961
1008
if (pgoptions && pgoptions[0] != '\0')
962
1009
{
963
1010
if (conn->pgoptions)
964
1011
free(conn->pgoptions);
965
1012
conn->pgoptions = strdup(pgoptions);
1013
+ if (!conn->pgoptions)
1014
+ goto oom_error;
966
1015
}
967
1016
968
1017
if (pgtty && pgtty[0] != '\0')
969
1018
{
970
1019
if (conn->pgtty)
971
1020
free(conn->pgtty);
972
1021
conn->pgtty = strdup(pgtty);
1022
+ if (!conn->pgtty)
1023
+ goto oom_error;
973
1024
}
974
1025
975
1026
if (login && login[0] != '\0')
976
1027
{
977
1028
if (conn->pguser)
978
1029
free(conn->pguser);
979
1030
conn->pguser = strdup(login);
1031
+ if (!conn->pguser)
1032
+ goto oom_error;
980
1033
}
981
1034
982
1035
if (pwd && pwd[0] != '\0')
983
1036
{
984
1037
if (conn->pgpass)
985
1038
free(conn->pgpass);
986
1039
conn->pgpass = strdup(pwd);
1040
+ if (!conn->pgpass)
1041
+ goto oom_error;
987
1042
}
988
1043
989
1044
/*
@@ -999,6 +1054,12 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
999
1054
(void) connectDBComplete(conn);
1000
1055
1001
1056
return conn;
1057
+
1058
+ oom_error:
1059
+ conn->status = CONNECTION_BAD;
1060
+ printfPQExpBuffer(&conn->errorMessage,
1061
+ libpq_gettext("out of memory\n"));
1062
+ return conn;
1002
1063
}
1003
1064
1004
1065
@@ -3760,7 +3821,16 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
3760
3821
if (strcmp(options[i].keyword, optname) == 0)
3761
3822
{
3762
3823
if (options[i].val == NULL)
3824
+ {
3763
3825
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
+ return 3;
3832
+ }
3833
+ }
3764
3834
found_keyword = true;
3765
3835
break;
3766
3836
}
@@ -3983,6 +4053,13 @@ parseServiceFile(const char *serviceFile,
3983
4053
{
3984
4054
if (options[i].val == NULL)
3985
4055
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
+ return 3;
4062
+ }
3986
4063
found_keyword = true;
3987
4064
break;
3988
4065
}
@@ -4402,6 +4479,14 @@ conninfo_array_parse(const char *const * keywords, const char *const * values,
4402
4479
if (options[k].val)
4403
4480
free(options[k].val);
4404
4481
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
+ return NULL;
4489
+ }
4405
4490
break;
4406
4491
}
4407
4492
}
@@ -4596,20 +4681,22 @@ conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
4596
4681
{
4597
4682
int prefix_len;
4598
4683
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;
4602
4686
char prevchar = '\0';
4603
4687
char *user = NULL;
4604
4688
char *host = NULL;
4605
4689
bool retval = false;
4606
4690
4691
+ /* need a modifiable copy of the input URI */
4692
+ buf = strdup(uri);
4607
4693
if (buf == NULL)
4608
4694
{
4609
4695
printfPQExpBuffer(errorMessage,
4610
4696
libpq_gettext("out of memory\n"));
4611
4697
return false;
4612
4698
}
4699
+ start = buf;
4613
4700
4614
4701
/* Skip the URI prefix */
4615
4702
prefix_len = uri_prefix_length(uri);
@@ -4951,15 +5038,17 @@ conninfo_uri_parse_params(char *params,
4951
5038
static char *
4952
5039
conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
4953
5040
{
4954
- char *buf = malloc(strlen(str) + 1) ;
4955
- char *p = buf ;
5041
+ char *buf;
5042
+ char *p;
4956
5043
const char *q = str;
4957
5044
5045
+ buf = malloc(strlen(str) + 1);
4958
5046
if (buf == NULL)
4959
5047
{
4960
5048
printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
4961
5049
return NULL;
4962
5050
}
5051
+ p = buf;
4963
5052
4964
5053
for (;;)
4965
5054
{
@@ -5104,7 +5193,6 @@ conninfo_storeval(PQconninfoOption *connOptions,
5104
5193
else
5105
5194
{
5106
5195
value_copy = strdup(value);
5107
-
5108
5196
if (value_copy == NULL)
5109
5197
{
5110
5198
printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
@@ -5672,6 +5760,12 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
5672
5760
ret = strdup(t);
5673
5761
fclose(fp);
5674
5762
5763
+ if (!ret)
5764
+ {
5765
+ /* Out of memory. XXX: an error message would be nice. */
5766
+ return NULL;
5767
+ }
5768
+
5675
5769
/* De-escape password. */
5676
5770
for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
5677
5771
{
0 commit comments