summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Roberson <josh@asteriasgi.com>2017-03-27 11:49:08 -0500
committertwisted <josh@asteriasgi.com>2017-03-29 07:53:43 -0600
commit43c785545be6402027a47f3ebae095bffc30eca7 (patch)
tree747e9af5eaa370b1def906640c015a2a64599ac2
parentf719c661a2113291b53e9b8e7002aba5d09ce92b (diff)
cel_pgsql.c: Fix buffer overflow calling libpq
PQEscapeStringConn() expects the buffer passed in to be an adequitely sized buffer to write out the escaped SQL value string into. It is possible, for large values (such as large values to Dial with a lot of devices) to have more than our 512+1 byte allocation and thus cause libpq to create a buffer overrun. glibc will nicely ABRT asterisk for you, citing a stack smash. Let's only allocate it to be as large as needed: If we have a value, then (strlen(value) * 2) + 1 (as recommended by libpq), and if we have none, just one byte to hold our null will do. ASTERISK-26896 #close Change-Id: If611c734292618ed68dde17816d09dd16667dea2
-rw-r--r--cel/cel_pgsql.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/cel/cel_pgsql.c b/cel/cel_pgsql.c
index e4e280e41..7ce76d298 100644
--- a/cel/cel_pgsql.c
+++ b/cel/cel_pgsql.c
@@ -181,11 +181,14 @@ static void pgsql_log(struct ast_event *event)
if (connected) {
struct columns *cur;
struct ast_str *sql = ast_str_create(maxsize), *sql2 = ast_str_create(maxsize2);
- char buf[257], escapebuf[513];
+ char buf[257];
+ char *escapebuf = NULL;
const char *value;
int first = 1;
+ size_t bufsize = 513;
- if (!sql || !sql2) {
+ escapebuf = ast_malloc(bufsize);
+ if (!escapebuf || !sql || !sql2) {
goto ast_log_cleanup;
}
@@ -309,6 +312,22 @@ static void pgsql_log(struct ast_event *event)
/* XXX Might want to handle dates, times, and other misc fields here XXX */
} else {
if (value) {
+ size_t required_size = strlen(value) * 2 + 1;
+
+ /* If our argument size exceeds our buffer, grow it,
+ * as PQescapeStringConn() expects the buffer to be
+ * adequitely sized and does *NOT* do size checking.
+ */
+ if (required_size > bufsize) {
+ char *tmpbuf = ast_realloc(escapebuf, required_size);
+
+ if (!tmpbuf) {
+ goto ast_log_cleanup;
+ }
+
+ escapebuf = tmpbuf;
+ bufsize = required_size;
+ }
PQescapeStringConn(conn, escapebuf, value, strlen(value), NULL);
} else {
escapebuf[0] = '\0';
@@ -379,6 +398,7 @@ static void pgsql_log(struct ast_event *event)
ast_log_cleanup:
ast_free(sql);
ast_free(sql2);
+ ast_free(escapebuf);
}
ast_mutex_unlock(&pgsql_lock);