]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared/varlink: add missing terminator in json strings
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 30 May 2019 16:35:22 +0000 (18:35 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 30 May 2019 16:45:06 +0000 (18:45 +0200)
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
src/shared/varlink.c
src/test/test-json.c

index 782d80af16aac0a2d77e591bd872b95e445340e2..baea31fed93bada63202267c7e54236ffcb0aa42 100644 (file)
@@ -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) {
index 3256a934901e213ba0ed0f6d4e7531c98574485f..45442848bd8154d43a8c8790485030252318365f 100644 (file)
@@ -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;
index 8bd6a7221cb1eb752d3642d3c6f554a37a70ff3a..a6613043b92408c9368df89e4f6e05dfe1a1d9a9 100644 (file)
@@ -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)