pkg_parse: fix segfault when parsing descriptions with leading newlines
authorJo-Philipp Wich <jo@mein.io>
Fri, 28 Jul 2017 11:02:08 +0000 (13:02 +0200)
committerMatthias Schiffer <mschiffer@universe-factory.net>
Mon, 23 Oct 2017 21:30:10 +0000 (23:30 +0200)
During parsing of multi-line descriptions that begin with a newline
character, the description pointer will be NULL when the first
continuation line is encountered, causing the strlen() invocation
on the description pointer to segfault.

This is caused by the fact that the parse_simple() helper used for
parsing the initial description line returns NULL instead of an
empty string when encountering only whitespace after the field name.

Rework the continuation line parsing code to not assume an initialized
pointer by checking before calling strlen() and avoiding realloc()
on a NULL pointer.

Fixes FS#933.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
libopkg/pkg_parse.c

index 121f147..d6fe546 100644 (file)
@@ -254,18 +254,16 @@ int pkg_parse_line(void *ptr, char *line, uint mask)
 
        case ' ':
                if ((mask & PFM_DESCRIPTION) && reading_description) {
-                       if (isatty(1)) {
-                               description = xrealloc(description,
-                                                           strlen(description)
-                                                           + 1 + strlen(line) +
-                                                           1);
+                       size_t len = (description ? strlen(description) : 0)
+                               + (isatty(1) ? 1 : 0) + strlen(line) + 1;
+
+                       description = description ? xrealloc(description, len)
+                               : xcalloc(len, 1);
+
+                       if (isatty(1))
                                strcat(description, "\n");
-                       } else {
-                               description = xrealloc(description,
-                                                           strlen(description)
-                                                           + 1 + strlen(line));
-                       }
-                       strcat(description, (line));
+
+                       strcat(description, line);
                        goto dont_reset_flags;
                } else if ((mask & PFM_CONFFILES) && reading_conffiles) {
                        parse_conffiles(pkg, line);