vcs-svn: improve reporting of input errors
[gitweb.git] / vcs-svn / svndump.c
index f07376f964d7a5b65cc1f5b2f4c8164bd5f2ab79..15f822ea844ba64a12d19e02e12f244b2f99d4cb 100644 (file)
@@ -149,6 +149,13 @@ static void handle_property(uint32_t key, const char *val, uint32_t len,
        }
 }
 
+static void die_short_read(void)
+{
+       if (buffer_ferror(&input))
+               die_errno("error reading dump file");
+       die("invalid dump: unexpected end of file");
+}
+
 static void read_props(void)
 {
        uint32_t key = ~0;
@@ -170,12 +177,21 @@ static void read_props(void)
                uint32_t len;
                const char *val;
                const char type = t[0];
+               int ch;
 
                if (!type || t[1] != ' ')
                        die("invalid property line: %s\n", t);
                len = atoi(&t[2]);
                val = buffer_read_string(&input, len);
-               buffer_skip_bytes(&input, 1);   /* Discard trailing newline. */
+               if (!val || strlen(val) != len)
+                       die_short_read();
+
+               /* Discard trailing newline. */
+               ch = buffer_read_char(&input);
+               if (ch == EOF)
+                       die_short_read();
+               if (ch != '\n')
+                       die("invalid dump: expected newline after %s", val);
 
                switch (type) {
                case 'K':
@@ -235,9 +251,7 @@ static void handle_node(void)
                uint32_t mode;
                if (!have_text)
                        mark = repo_read_path(node_ctx.dst);
-               mode = repo_modify_path(node_ctx.dst, 0, 0);
-               if (!mode)
-                       die("invalid dump: path to be modified is missing");
+               mode = repo_read_mode(node_ctx.dst);
                if (mode == REPO_MODE_DIR && type != REPO_MODE_DIR)
                        die("invalid dump: cannot modify a directory into a file");
                if (mode != REPO_MODE_DIR && type == REPO_MODE_DIR)
@@ -346,7 +360,11 @@ void svndump_read(const char *url)
                        node_ctx.prop_delta = !strcmp(val, "true");
                } else if (key == keys.content_length) {
                        len = atoi(val);
-                       buffer_read_line(&input);
+                       t = buffer_read_line(&input);
+                       if (!t)
+                               die_short_read();
+                       if (*t)
+                               die("invalid dump: expected blank line after content length header");
                        if (active_ctx == REV_CTX) {
                                read_props();
                        } else if (active_ctx == NODE_CTX) {
@@ -354,10 +372,13 @@ void svndump_read(const char *url)
                                active_ctx = REV_CTX;
                        } else {
                                fprintf(stderr, "Unexpected content length header: %"PRIu32"\n", len);
-                               buffer_skip_bytes(&input, len);
+                               if (buffer_skip_bytes(&input, len) != len)
+                                       die_short_read();
                        }
                }
        }
+       if (buffer_ferror(&input))
+               die_short_read();
        if (active_ctx == NODE_CTX)
                handle_node();
        if (active_ctx != DUMP_CTX)