Skip to content

Commit 08dc7a5

Browse files
author
Commitfest Bot
committed
[CF 5910] v8 - Add proper checks for ecpg_strdup() return value
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5910 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/CAJ7c6TNX+sL6YLdOVcaHhh_aXQzC3ggfw8vcygJhrNbSzcNEig@mail.gmail.com Author(s): Aleksander Alekseev, Evgeniy Gorbanev
2 parents 0810fbb + 33d2101 commit 08dc7a5

File tree

6 files changed

+117
-40
lines changed

6 files changed

+117
-40
lines changed

src/interfaces/ecpg/ecpglib/connect.c

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
259259
struct connection *this;
260260
int i,
261261
connect_params = 0;
262-
char *dbname = name ? ecpg_strdup(name, lineno) : NULL,
262+
bool alloc_failed = (sqlca == NULL);
263+
char *dbname = name ? ecpg_strdup(name, lineno, &alloc_failed) : NULL,
263264
*host = NULL,
264265
*tmp,
265266
*port = NULL,
@@ -268,7 +269,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
268269
const char **conn_keywords;
269270
const char **conn_values;
270271

271-
if (sqlca == NULL)
272+
if (alloc_failed)
272273
{
273274
ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
274275
ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
@@ -297,7 +298,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
297298
if (envname)
298299
{
299300
ecpg_free(dbname);
300-
dbname = ecpg_strdup(envname, lineno);
301+
dbname = ecpg_strdup(envname, lineno, &alloc_failed);
301302
}
302303
}
303304

@@ -349,7 +350,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
349350
tmp = strrchr(dbname + offset, '?');
350351
if (tmp != NULL) /* options given */
351352
{
352-
options = ecpg_strdup(tmp + 1, lineno);
353+
options = ecpg_strdup(tmp + 1, lineno, &alloc_failed);
353354
*tmp = '\0';
354355
}
355356

@@ -358,7 +359,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
358359
{
359360
if (tmp[1] != '\0') /* non-empty database name */
360361
{
361-
realname = ecpg_strdup(tmp + 1, lineno);
362+
realname = ecpg_strdup(tmp + 1, lineno, &alloc_failed);
362363
connect_params++;
363364
}
364365
*tmp = '\0';
@@ -368,7 +369,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
368369
if (tmp != NULL) /* port number given */
369370
{
370371
*tmp = '\0';
371-
port = ecpg_strdup(tmp + 1, lineno);
372+
port = ecpg_strdup(tmp + 1, lineno, &alloc_failed);
372373
connect_params++;
373374
}
374375

@@ -402,7 +403,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
402403
{
403404
if (*(dbname + offset) != '\0')
404405
{
405-
host = ecpg_strdup(dbname + offset, lineno);
406+
host = ecpg_strdup(dbname + offset, lineno, &alloc_failed);
406407
connect_params++;
407408
}
408409
}
@@ -414,22 +415,22 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
414415
tmp = strrchr(dbname, ':');
415416
if (tmp != NULL) /* port number given */
416417
{
417-
port = ecpg_strdup(tmp + 1, lineno);
418+
port = ecpg_strdup(tmp + 1, lineno, &alloc_failed);
418419
connect_params++;
419420
*tmp = '\0';
420421
}
421422

422423
tmp = strrchr(dbname, '@');
423424
if (tmp != NULL) /* host name given */
424425
{
425-
host = ecpg_strdup(tmp + 1, lineno);
426+
host = ecpg_strdup(tmp + 1, lineno, &alloc_failed);
426427
connect_params++;
427428
*tmp = '\0';
428429
}
429430

430431
if (strlen(dbname) > 0)
431432
{
432-
realname = ecpg_strdup(dbname, lineno);
433+
realname = ecpg_strdup(dbname, lineno, &alloc_failed);
433434
connect_params++;
434435
}
435436
else
@@ -460,7 +461,18 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
460461
*/
461462
conn_keywords = (const char **) ecpg_alloc((connect_params + 1) * sizeof(char *), lineno);
462463
conn_values = (const char **) ecpg_alloc(connect_params * sizeof(char *), lineno);
463-
if (conn_keywords == NULL || conn_values == NULL)
464+
465+
/* Decide on a connection name */
466+
if (connection_name != NULL || realname != NULL)
467+
{
468+
this->name = ecpg_strdup(connection_name ? connection_name : realname,
469+
lineno, &alloc_failed);
470+
}
471+
else
472+
this->name = NULL;
473+
474+
/* Deal with any failed allocations above */
475+
if (conn_keywords == NULL || conn_values == NULL || alloc_failed)
464476
{
465477
if (host)
466478
ecpg_free(host);
@@ -476,6 +488,8 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
476488
ecpg_free(conn_keywords);
477489
if (conn_values)
478490
ecpg_free(conn_values);
491+
if (this->name)
492+
ecpg_free(this->name);
479493
free(this);
480494
return false;
481495
}
@@ -510,17 +524,14 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
510524
ecpg_free(conn_keywords);
511525
if (conn_values)
512526
ecpg_free(conn_values);
527+
if (this->name)
528+
ecpg_free(this->name);
513529
free(this);
514530
return false;
515531
}
516532
}
517533
#endif
518534

519-
if (connection_name != NULL)
520-
this->name = ecpg_strdup(connection_name, lineno);
521-
else
522-
this->name = ecpg_strdup(realname, lineno);
523-
524535
this->cache_head = NULL;
525536
this->prep_stmts = NULL;
526537

src/interfaces/ecpg/ecpglib/descriptor.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,9 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
240240
act_tuple;
241241
struct variable data_var;
242242
struct sqlca_t *sqlca = ECPGget_sqlca();
243+
bool alloc_failed = (sqlca == NULL);
243244

244-
if (sqlca == NULL)
245+
if (alloc_failed)
245246
{
246247
ecpg_raise(lineno, ECPG_OUT_OF_MEMORY,
247248
ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
@@ -493,7 +494,14 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
493494
#ifdef WIN32
494495
stmt.oldthreadlocale = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
495496
#endif
496-
stmt.oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno);
497+
stmt.oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL),
498+
lineno, &alloc_failed);
499+
if (alloc_failed)
500+
{
501+
va_end(args);
502+
return false;
503+
}
504+
497505
setlocale(LC_NUMERIC, "C");
498506
#endif
499507

src/interfaces/ecpg/ecpglib/ecpglib_extern.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ void ecpg_free(void *ptr);
175175
bool ecpg_init(const struct connection *con,
176176
const char *connection_name,
177177
const int lineno);
178-
char *ecpg_strdup(const char *string, int lineno);
178+
char *ecpg_strdup(const char *string, int lineno, bool *alloc_failed);
179179
const char *ecpg_type_name(enum ECPGttype typ);
180180
int ecpg_dynamic_type(Oid type);
181181
int sqlda_dynamic_type(Oid type, enum COMPAT_MODE compat);

src/interfaces/ecpg/ecpglib/execute.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -860,9 +860,9 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
860860
numeric *nval;
861861

862862
if (var->arrsize > 1)
863-
mallocedval = ecpg_strdup("{", lineno);
863+
mallocedval = ecpg_strdup("{", lineno, NULL);
864864
else
865-
mallocedval = ecpg_strdup("", lineno);
865+
mallocedval = ecpg_strdup("", lineno, NULL);
866866

867867
if (!mallocedval)
868868
return false;
@@ -923,9 +923,9 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
923923
int slen;
924924

925925
if (var->arrsize > 1)
926-
mallocedval = ecpg_strdup("{", lineno);
926+
mallocedval = ecpg_strdup("{", lineno, NULL);
927927
else
928-
mallocedval = ecpg_strdup("", lineno);
928+
mallocedval = ecpg_strdup("", lineno, NULL);
929929

930930
if (!mallocedval)
931931
return false;
@@ -970,9 +970,9 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
970970
int slen;
971971

972972
if (var->arrsize > 1)
973-
mallocedval = ecpg_strdup("{", lineno);
973+
mallocedval = ecpg_strdup("{", lineno, NULL);
974974
else
975-
mallocedval = ecpg_strdup("", lineno);
975+
mallocedval = ecpg_strdup("", lineno, NULL);
976976

977977
if (!mallocedval)
978978
return false;
@@ -1017,9 +1017,9 @@ ecpg_store_input(const int lineno, const bool force_indicator, const struct vari
10171017
int slen;
10181018

10191019
if (var->arrsize > 1)
1020-
mallocedval = ecpg_strdup("{", lineno);
1020+
mallocedval = ecpg_strdup("{", lineno, NULL);
10211021
else
1022-
mallocedval = ecpg_strdup("", lineno);
1022+
mallocedval = ecpg_strdup("", lineno, NULL);
10231023

10241024
if (!mallocedval)
10251025
return false;
@@ -2001,7 +2001,8 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
20012001
return false;
20022002
}
20032003
#endif
2004-
stmt->oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno);
2004+
stmt->oldlocale = ecpg_strdup(setlocale(LC_NUMERIC, NULL), lineno,
2005+
NULL);
20052006
if (stmt->oldlocale == NULL)
20062007
{
20072008
ecpg_do_epilogue(stmt);
@@ -2030,7 +2031,14 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
20302031
statement_type = ECPGst_execute;
20312032
}
20322033
else
2033-
stmt->command = ecpg_strdup(query, lineno);
2034+
{
2035+
stmt->command = ecpg_strdup(query, lineno, NULL);
2036+
if (!stmt->command)
2037+
{
2038+
ecpg_do_epilogue(stmt);
2039+
return false;
2040+
}
2041+
}
20342042

20352043
stmt->name = NULL;
20362044

@@ -2042,7 +2050,12 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
20422050
if (command)
20432051
{
20442052
stmt->name = stmt->command;
2045-
stmt->command = ecpg_strdup(command, lineno);
2053+
stmt->command = ecpg_strdup(command, lineno, NULL);
2054+
if (!stmt->command)
2055+
{
2056+
ecpg_do_epilogue(stmt);
2057+
return false;
2058+
}
20462059
}
20472060
else
20482061
{
@@ -2175,7 +2188,12 @@ ecpg_do_prologue(int lineno, const int compat, const int force_indicator,
21752188

21762189
if (!is_prepared_name_set && stmt->statement_type == ECPGst_prepare)
21772190
{
2178-
stmt->name = ecpg_strdup(var->value, lineno);
2191+
stmt->name = ecpg_strdup(var->value, lineno, NULL);
2192+
if (!stmt->name)
2193+
{
2194+
ecpg_do_epilogue(stmt);
2195+
return false;
2196+
}
21792197
is_prepared_name_set = true;
21802198
}
21812199
}

src/interfaces/ecpg/ecpglib/memory.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,15 @@ ecpg_realloc(void *ptr, long size, int lineno)
4343
return new;
4444
}
4545

46+
/*
47+
* Wrapper for strdup(), with NULL in input treated as a correct case.
48+
*
49+
* "alloc_failed" can be optionally specified by the caller to check for
50+
* allocation failures. The caller is responsible for its initialization,
51+
* as ecpg_strdup() may be called repeatedly across multiple allocations.
52+
*/
4653
char *
47-
ecpg_strdup(const char *string, int lineno)
54+
ecpg_strdup(const char *string, int lineno, bool *alloc_failed)
4855
{
4956
char *new;
5057

@@ -54,6 +61,8 @@ ecpg_strdup(const char *string, int lineno)
5461
new = strdup(string);
5562
if (!new)
5663
{
64+
if (alloc_failed)
65+
*alloc_failed = true;
5766
ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
5867
return NULL;
5968
}

0 commit comments

Comments
 (0)