summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2020-01-20 00:15:15 +0000
committerTom Lane2020-01-20 00:15:15 +0000
commit44f1fc8df5dadbc5e80661660903aab4076d868f (patch)
treec86300ddb7c33b3a584d68f639899a8694ea84a9
parent9c679a08f0cdedcf7f084daea3cba6ae9c3cbced (diff)
Fix out-of-memory handling in ecpglib.
ecpg_build_params() would crash on a null pointer dereference if realloc() failed, due to updating the persistent "stmt" struct too aggressively. (Even without the crash, this would've leaked the old storage that we were trying to realloc.) Per Coverity. This seems to have been broken in commit 0cc050794, so back-patch into v12.
-rw-r--r--src/interfaces/ecpg/ecpglib/execute.c37
1 files changed, 24 insertions, 13 deletions
diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c
index e261cf9167..59e8e3a825 100644
--- a/src/interfaces/ecpg/ecpglib/execute.c
+++ b/src/interfaces/ecpg/ecpglib/execute.c
@@ -1499,26 +1499,37 @@ ecpg_build_params(struct statement *stmt)
}
else
{
- if (!(stmt->paramvalues = (char **) ecpg_realloc(stmt->paramvalues, sizeof(char *) * (stmt->nparams + 1), stmt->lineno)))
+ bool realloc_failed = false;
+ char **newparamvalues;
+ int *newparamlengths;
+ int *newparamformats;
+
+ /* enlarge all the param arrays */
+ if ((newparamvalues = (char **) ecpg_realloc(stmt->paramvalues, sizeof(char *) * (stmt->nparams + 1), stmt->lineno)))
+ stmt->paramvalues = newparamvalues;
+ else
+ realloc_failed = true;
+
+ if ((newparamlengths = (int *) ecpg_realloc(stmt->paramlengths, sizeof(int) * (stmt->nparams + 1), stmt->lineno)))
+ stmt->paramlengths = newparamlengths;
+ else
+ realloc_failed = true;
+
+ if ((newparamformats = (int *) ecpg_realloc(stmt->paramformats, sizeof(int) * (stmt->nparams + 1), stmt->lineno)))
+ stmt->paramformats = newparamformats;
+ else
+ realloc_failed = true;
+
+ if (realloc_failed)
{
ecpg_free_params(stmt, false);
ecpg_free(tobeinserted);
return false;
}
- stmt->paramvalues[stmt->nparams] = tobeinserted;
- if (!(stmt->paramlengths = (int *) ecpg_realloc(stmt->paramlengths, sizeof(int) * (stmt->nparams + 1), stmt->lineno)))
- {
- ecpg_free_params(stmt, false);
- return false;
- }
+ /* only now can we assign ownership of "tobeinserted" to stmt */
+ stmt->paramvalues[stmt->nparams] = tobeinserted;
stmt->paramlengths[stmt->nparams] = binary_length;
-
- if (!(stmt->paramformats = (int *) ecpg_realloc(stmt->paramformats, sizeof(int) * (stmt->nparams + 1), stmt->lineno)))
- {
- ecpg_free_params(stmt, false);
- return false;
- }
stmt->paramformats[stmt->nparams] = (binary_format ? 1 : 0);
stmt->nparams++;