Hi all, In ecpg_add_mem of memory.c, we use ecpg_alloc but there is actually no NULL-pointer check. If an OOM shows up exactly at this point, this is likely to cause a crash. Attached patch adds some extra processing to ecpg_add_mem to check if the allocation fails, and to fail properly if an OOM appears. This issue has been pointed out by Coverity, and I guessed the legwork needed by myself. Regards, -- Michael
From 250349c31f86028284bb94f896916a0bb449d299 Mon Sep 17 00:00:00 2001 From: Michael Paquier <michael@otacoo.com> Date: Tue, 3 Feb 2015 16:21:50 +0900 Subject: [PATCH] Fix unlikely-to-happen crash in ecpg_add_mem
This routine was called ecpg_alloc to allocate to memory but did not actually check the returned pointer allocated, potentially NULL which is actually the result of a malloc call. Issue noted by Coverity, though I guessed the legwork needed here. --- src/interfaces/ecpg/ecpglib/descriptor.c | 14 ++++++++++++-- src/interfaces/ecpg/ecpglib/execute.c | 12 ++++++++++-- src/interfaces/ecpg/ecpglib/extern.h | 2 +- src/interfaces/ecpg/ecpglib/memory.c | 9 ++++++++- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c index b2990ca..bfa3e287 100644 --- a/src/interfaces/ecpg/ecpglib/descriptor.c +++ b/src/interfaces/ecpg/ecpglib/descriptor.c @@ -440,7 +440,12 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...) return false; } *(void **) var = mem; - ecpg_add_mem(mem, lineno); + if (!ecpg_add_mem(mem, lineno)) + { + ecpg_free(mem); + va_end(args); + return false; + } var = mem; } @@ -518,7 +523,12 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...) return false; } *(void **) data_var.ind_pointer = mem; - ecpg_add_mem(mem, lineno); + if (!ecpg_add_mem(mem, lineno)) + { + ecpg_free(mem); + va_end(args); + return false; + } data_var.ind_value = mem; } diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index abe60a5..912e75c 100644 --- a/src/interfaces/ecpg/ecpglib/execute.c +++ b/src/interfaces/ecpg/ecpglib/execute.c @@ -402,7 +402,11 @@ ecpg_store_result(const PGresult *results, int act_field, if (!var->value) return false; *((char **) var->pointer) = var->value; - ecpg_add_mem(var->value, stmt->lineno); + if (!ecpg_add_mem(var->value, stmt->lineno)) + { + ecpg_free(var->value); + return false; + } } /* allocate indicator variable if needed */ @@ -414,7 +418,11 @@ ecpg_store_result(const PGresult *results, int act_field, if (!var->ind_value) return false; *((char **) var->ind_pointer) = var->ind_value; - ecpg_add_mem(var->ind_value, stmt->lineno); + if (!ecpg_add_mem(var->ind_value, stmt->lineno)) + { + ecpg_free(var->ind_value); + return false; + } } /* fill the variable with the tuple(s) */ diff --git a/src/interfaces/ecpg/ecpglib/extern.h b/src/interfaces/ecpg/ecpglib/extern.h index 3836007..3e93b53 100644 --- a/src/interfaces/ecpg/ecpglib/extern.h +++ b/src/interfaces/ecpg/ecpglib/extern.h @@ -137,7 +137,7 @@ extern struct var_list *ivlist; /* Here are some methods used by the lib. */ /* Returns a pointer to a string containing a simple type name. */ -void ecpg_add_mem(void *ptr, int lineno); +bool ecpg_add_mem(void *ptr, int lineno); bool ecpg_get_data(const PGresult *, int, int, int, enum ECPGttype type, enum ECPGttype, char *, char *, long, long, long, diff --git a/src/interfaces/ecpg/ecpglib/memory.c b/src/interfaces/ecpg/ecpglib/memory.c index a09cd26..1ffe3e1 100644 --- a/src/interfaces/ecpg/ecpglib/memory.c +++ b/src/interfaces/ecpg/ecpglib/memory.c @@ -104,14 +104,21 @@ static struct auto_mem *auto_allocs = NULL; #define set_auto_allocs(am) do { auto_allocs = (am); } while(0) #endif -void +bool ecpg_add_mem(void *ptr, int lineno) { struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), lineno); + if (!am) + { + ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL); + return false; + } + am->pointer = ptr; am->next = get_auto_allocs(); set_auto_allocs(am); + return true; } void -- 2.2.2
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers