summaryrefslogtreecommitdiff
blob: 20c4c8f2688a3685842fb1c12bd62f95a6ba97a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Index: lib/libarchive/archive_read_support_compression_none.c
===================================================================
RCS file: /home/ncvs/src/lib/libarchive/archive_read_support_compression_none.c,v
retrieving revision 1.8
diff -u -I__FBSDID -r1.8 archive_read_support_compression_none.c
--- lib/libarchive/archive_read_support_compression_none.c	29 Aug 2006 04:59:25 -0000	1.8
+++ lib/libarchive/archive_read_support_compression_none.c	2 Nov 2006 05:17:28 -0000
@@ -257,7 +257,9 @@
 }
 
 /*
- * Skip at most request bytes. Skipped data is marked as consumed.
+ * Skip forward by exactly the requested bytes or else return
+ * ARCHIVE_FATAL.  Note that this differs from the contract for
+ * read_ahead, which does not gaurantee a minimum count.
  */
 static ssize_t
 archive_decompressor_none_skip(struct archive *a, size_t request)
@@ -287,9 +289,7 @@
 	if (request == 0)
 		return (total_bytes_skipped);
 	/*
-	 * If no client_skipper is provided, just read the old way. It is very
-	 * likely that after skipping, the request has not yet been fully
-	 * satisfied (and is still > 0). In that case, read as well.
+	 * If a client_skipper was provided, try that first.
 	 */
 	if (a->client_skipper != NULL) {
 		bytes_skipped = (a->client_skipper)(a, a->client_data,
@@ -307,6 +307,12 @@
 		a->raw_position += bytes_skipped;
 		state->client_avail = state->client_total = 0;
 	}
+	/*
+	 * Note that client_skipper will usually not satisfy the
+	 * full request (due to low-level blocking concerns),
+	 * so even if client_skipper is provided, we may still
+	 * have to use ordinary reads to finish out the request.
+	 */
 	while (request > 0) {
 		const void* dummy_buffer;
 		ssize_t bytes_read;
@@ -314,6 +320,12 @@
 		    &dummy_buffer, request);
 		if (bytes_read < 0)
 			return (bytes_read);
+		if (bytes_read == 0) {
+			/* We hit EOF before we satisfied the skip request. */
+			archive_set_error(a, ARCHIVE_ERRNO_MISC,
+			    "Truncated input file (need to skip %d bytes)", (int)request);
+			return (ARCHIVE_FATAL);
+		}
 		assert(bytes_read >= 0); /* precondition for cast below */
 		min = minimum((size_t)bytes_read, request);
 		bytes_read = archive_decompressor_none_read_consume(a, min);