From 2a04712c19556517b47215d49b3faea14490a4f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 30 May 2019 18:35:22 +0200 Subject: [PATCH] shared/varlink: add missing terminator in json strings Should finally fix oss-fuzz-14688. 8688c29b5aece49805a244676cba5bba0196f509 wasn't enough. The buffer retrieved from memstream has the size that the same as the written data. When we write do write(f, s, strlen(s)), then no terminating NUL is written, and the buffer is not (necessarilly) a proper C string. --- src/shared/json.c | 10 ++++++++-- src/shared/varlink.c | 1 + src/test/test-json.c | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/shared/json.c b/src/shared/json.c index 782d80af16..baea31fed9 100644 --- a/src/shared/json.c +++ b/src/shared/json.c @@ -1555,6 +1555,9 @@ int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) { size_t sz = 0; int r; + /* Returns the length of the generated string (without the terminating NUL), + * or negative on error. */ + assert_return(v, -EINVAL); assert_return(ret, -EINVAL); @@ -1567,6 +1570,9 @@ int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) { json_variant_dump(v, flags, f, NULL); + /* Add terminating 0, so that the output buffer is a valid string. */ + fputc('\0', f); + r = fflush_and_check(f); } if (r < 0) @@ -1574,8 +1580,8 @@ int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) { assert(s); *ret = TAKE_PTR(s); - - return (int) sz; + assert(sz > 0); + return (int) sz - 1; } void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix) { diff --git a/src/shared/varlink.c b/src/shared/varlink.c index 3256a93490..45442848bd 100644 --- a/src/shared/varlink.c +++ b/src/shared/varlink.c @@ -1212,6 +1212,7 @@ static int varlink_enqueue_json(Varlink *v, JsonVariant *m) { r = json_variant_format(m, 0, &text); if (r < 0) return r; + assert(text[r] == '\0'); if (v->output_buffer_size + r + 1 > VARLINK_BUFFER_MAX) return -ENOBUFS; diff --git a/src/test/test-json.c b/src/test/test-json.c index 8bd6a7221c..a6613043b9 100644 --- a/src/test/test-json.c +++ b/src/test/test-json.c @@ -89,6 +89,7 @@ static void test_variant(const char *data, Test test) { r = json_variant_format(v, 0, &s); assert_se(r >= 0); assert_se(s); + assert_se((size_t) r == strlen(s)); log_info("formatted normally: %s\n", s); @@ -105,6 +106,7 @@ static void test_variant(const char *data, Test test) { r = json_variant_format(v, JSON_FORMAT_PRETTY, &s); assert_se(r >= 0); assert_se(s); + assert_se((size_t) r == strlen(s)); log_info("formatted prettily:\n%s", s); @@ -120,12 +122,14 @@ static void test_variant(const char *data, Test test) { r = json_variant_format(v, JSON_FORMAT_COLOR, &s); assert_se(r >= 0); assert_se(s); + assert_se((size_t) r == strlen(s)); printf("Normal with color: %s\n", s); s = mfree(s); r = json_variant_format(v, JSON_FORMAT_COLOR|JSON_FORMAT_PRETTY, &s); assert_se(r >= 0); assert_se(s); + assert_se((size_t) r == strlen(s)); printf("Pretty with color:\n%s\n", s); if (test)