vcs-svn: improve reporting of input errors
Catch input errors and exit early enough to print a reasonable diagnosis based on errno. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: David Barr <david.barr@cordelta.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Jonathan Nieder committed
Dec 28, 2010 at 04:30 UTC
c9d1c8ba059577e64fb2213cb0c5f3c4619c7519
2 files changed
+37
-5
vcs-svn/fast_export.c
+11
-2
@@ -63,14 +63,23 @@ void fast_export_commit(uint32_t revision, uint32_t author, char *log,
63
printf("progress Imported commit %"PRIu32".\n\n", revision);
64
}
65
66
+static void die_short_read(struct line_buffer *input)
67
+{
68
+ if (buffer_ferror(input))
69
+ die_errno("error reading dump file");
70
+ die("invalid dump: unexpected end of file");
71
+}
72
+
73
void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len, struct line_buffer *input)
74
{
75
if (mode == REPO_MODE_LNK) {
76
/* svn symlink blobs start with "link " */
70
- buffer_skip_bytes(input, 5);
77
len -= 5;
78
+ if (buffer_skip_bytes(input, 5) != 5)
79
+ die_short_read(input);
80
}
81
printf("blob\nmark :%"PRIu32"\ndata %"PRIu32"\n", mark, len);
74
- buffer_copy_bytes(input, len);
82
+ if (buffer_copy_bytes(input, len) != len)
83
+ die_short_read(input);
84
fputc('\n', stdout);
85
}
vcs-svn/svndump.c
+26
-3
@@ -149,6 +149,13 @@ static void handle_property(uint32_t key, const char *val, uint32_t len,
149
}
150
}
151
152
+static void die_short_read(void)
153
+{
154
+ if (buffer_ferror(&input))
155
+ die_errno("error reading dump file");
156
+ die("invalid dump: unexpected end of file");
157
+}
158
+
159
static void read_props(void)
160
{
161
uint32_t key = ~0;
@@ -170,12 +177,21 @@ static void read_props(void)
177
uint32_t len;
178
const char *val;
179
const char type = t[0];
180
+ int ch;
181
182
if (!type || t[1] != ' ')
183
die("invalid property line: %s\n", t);
184
len = atoi(&t[2]);
185
val = buffer_read_string(&input, len);
178
- buffer_skip_bytes(&input, 1); /* Discard trailing newline. */
186
+ if (!val || strlen(val) != len)
187
+ die_short_read();
188
+
189
+ /* Discard trailing newline. */
190
+ ch = buffer_read_char(&input);
191
+ if (ch == EOF)
192
+ die_short_read();
193
+ if (ch != '\n')
194
+ die("invalid dump: expected newline after %s", val);
195
196
switch (type) {
197
case 'K':
@@ -344,7 +360,11 @@ void svndump_read(const char *url)
360
node_ctx.prop_delta = !strcmp(val, "true");
361
} else if (key == keys.content_length) {
362
len = atoi(val);
347
- buffer_read_line(&input);
363
+ t = buffer_read_line(&input);
364
+ if (!t)
365
+ die_short_read();
366
+ if (*t)
367
+ die("invalid dump: expected blank line after content length header");
368
if (active_ctx == REV_CTX) {
369
read_props();
370
} else if (active_ctx == NODE_CTX) {
@@ -352,10 +372,13 @@ void svndump_read(const char *url)
372
active_ctx = REV_CTX;
373
} else {
374
fprintf(stderr, "Unexpected content length header: %"PRIu32"\n", len);
355
- buffer_skip_bytes(&input, len);
375
+ if (buffer_skip_bytes(&input, len) != len)
376
+ die_short_read();
377
}
378
}
379
}
380
+ if (buffer_ferror(&input))
381
+ die_short_read();
382
if (active_ctx == NODE_CTX)
383
handle_node();
384
if (active_ctx != DUMP_CTX)