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 <[email protected]>
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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers