summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Svensson <bjorn.a.svensson@est.tech>2022-09-01 13:47:54 +0200
committerMichael Grunder <michael.grunder@gmail.com>2022-09-01 10:35:07 -0700
commit329eaf9bae314f8bc307c809340b262f67c2ce36 (patch)
tree39eea1f77463681efb497fdaccabf73a64c6e9d7
parenteaae7321c2c84c45f40ccb01233d299644f4e786 (diff)
Fix heap-buffer-overflow issue in redisvFormatCommad
A command with a faulty formatting string that lacks the conversion specifier results in a ASAN heap-buffer-overflow. This was due to that strchr() matches on null-termination, which triggers a continuation of the string parsing.
-rw-r--r--hiredis.c5
-rw-r--r--test.c6
2 files changed, 10 insertions, 1 deletions
diff --git a/hiredis.c b/hiredis.c
index 1fd8570..6c48d66 100644
--- a/hiredis.c
+++ b/hiredis.c
@@ -402,6 +402,11 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
/* Copy va_list before consuming with va_arg */
va_copy(_cpy,ap);
+ /* Make sure we have more characters otherwise strchr() accepts
+ * '\0' as an integer specifier. This is checked after above
+ * va_copy() to avoid UB in fmt_invalid's call to va_end(). */
+ if (*_p == '\0') goto fmt_invalid;
+
/* Integer conversion (without modifiers) */
if (strchr(intfmts,*_p) != NULL) {
va_arg(ap,int);
diff --git a/test.c b/test.c
index 7d3e70a..e4aad54 100644
--- a/test.c
+++ b/test.c
@@ -339,10 +339,14 @@ static void test_format_commands(void) {
FLOAT_WIDTH_TEST(float);
FLOAT_WIDTH_TEST(double);
- test("Format command with invalid printf format: ");
+ test("Format command with unhandled printf format (specifier 'p' not supported): ");
len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",(size_t)3);
test_cond(len == -1);
+ test("Format command with invalid printf format (specifier missing): ");
+ len = redisFormatCommand(&cmd,"%-");
+ test_cond(len == -1);
+
const char *argv[3];
argv[0] = "SET";
argv[1] = "foo\0xxx";