diff --git a/src/adb.c b/src/adb.c
index 398c9b2877826dc89c2d1fd8870a28b0bdf273ab..fee76b9960b5b4de19f618e295cf32854f1cf1ac 100644
--- a/src/adb.c
+++ b/src/adb.c
@@ -313,7 +313,7 @@ static int __adb_m_stream(struct adb *db, struct apk_istream *is, uint32_t expec
 		if (r < 0) break;
 
 	skip_padding:
-		r = apk_istream_read(is, 0, adb_block_padding(&blk));
+		r = apk_istream_skip(is, adb_block_padding(&blk));
 		if (r < 0) break;
 	} while (1);
 err:
diff --git a/src/apk_io.h b/src/apk_io.h
index 6ec643ba433deeea01050fc509f6c63f823823c2..3cf48697fd33b35323d7c9fac1c6910e73fab928 100644
--- a/src/apk_io.h
+++ b/src/apk_io.h
@@ -110,6 +110,7 @@ void *apk_istream_get(struct apk_istream *is, size_t len);
 int apk_istream_get_max(struct apk_istream *is, size_t size, apk_blob_t *data);
 int apk_istream_get_delim(struct apk_istream *is, apk_blob_t token, apk_blob_t *data);
 static inline int apk_istream_get_all(struct apk_istream *is, apk_blob_t *data) { return apk_istream_get_max(is, APK_IO_ALL, data); }
+int apk_istream_skip(struct apk_istream *is, uint64_t size);
 int64_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, uint64_t size, struct apk_digest_ctx *dctx);
 
 static inline struct apk_istream *apk_istream_from_url(const char *url, time_t since)
diff --git a/src/extract_v3.c b/src/extract_v3.c
index 62cb69a75d8ce27dbfa5616aa16e322bd9d2ddff..a8083e4d8d4a855c4107eb87a77998edcdc4b679 100644
--- a/src/extract_v3.c
+++ b/src/extract_v3.c
@@ -231,7 +231,7 @@ static int apk_extract_v3_verify_meta(struct apk_extract_ctx *ectx, struct adb_o
 static int apk_extract_v3_verify_file(struct apk_extract_ctx *ectx, const struct apk_file_info *fi, struct apk_istream *is)
 {
 	if (is) {
-		apk_istream_read(is, 0, fi->size);
+		apk_istream_skip(is, fi->size);
 		return apk_istream_close(is);
 	}
 	return 0;
diff --git a/src/io.c b/src/io.c
index 065e985f68655f323a71d1e0aaae64f18422dea2..28b07f81af6e246e2c8e535b01aaa1419fef6d48 100644
--- a/src/io.c
+++ b/src/io.c
@@ -97,17 +97,15 @@ ssize_t apk_istream_read_max(struct apk_istream *is, void *ptr, size_t size)
 	while (left) {
 		if (is->ptr != is->end) {
 			r = min(left, is->end - is->ptr);
-			if (ptr) {
-				memcpy(ptr, is->ptr, r);
-				ptr += r;
-			}
+			memcpy(ptr, is->ptr, r);
+			ptr += r;
 			is->ptr += r;
 			left -= r;
 			continue;
 		}
 		if (is->err) break;
 
-		if (ptr && left > is->buf_size/4) {
+		if (left > is->buf_size/4) {
 			r = is->ops->read(is, ptr, left);
 			if (r <= 0) break;
 			left -= r;
@@ -283,14 +281,10 @@ static ssize_t segment_read(struct apk_istream *is, void *ptr, size_t size)
 
 static int segment_close(struct apk_istream *is)
 {
-	int r = is->err;
 	struct apk_segment_istream *sis = container_of(is, struct apk_segment_istream, is);
 
-	if (sis->bytes_left) {
-		apk_istream_read(sis->pis, NULL, sis->bytes_left);
-		sis->bytes_left = 0;
-	}
-	return r < 0 ? r : 0;
+	if (sis->bytes_left) apk_istream_skip(is, sis->bytes_left);
+	return is->err < 0 ? is->err : 0;
 }
 
 static const struct apk_istream_ops segment_istream_ops = {
@@ -628,6 +622,22 @@ struct apk_istream *__apk_istream_from_file(int atfd, const char *file, int try_
 	return apk_istream_from_fd(fd);
 }
 
+int apk_istream_skip(struct apk_istream *is, uint64_t size)
+{
+	uint64_t done = 0;
+	apk_blob_t d;
+	int r;
+
+	if (IS_ERR(is)) return PTR_ERR(is);
+
+	while (done < size) {
+		r = apk_istream_get_max(is, min(size - done, SSIZE_MAX), &d);
+		if (r < 0) return r;
+		done += d.len;
+	}
+	return done;
+}
+
 int64_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, uint64_t size, struct apk_digest_ctx *dctx)
 {
 	uint64_t done = 0;
diff --git a/src/tar.c b/src/tar.c
index 752d983e8c6a139f40a3fbfc2635348e1fab96ec..14e6a56c9d2bbee0c40f22a61af015fb594cf8c2 100644
--- a/src/tar.c
+++ b/src/tar.c
@@ -239,7 +239,7 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser,
 			paxlen = 0;
 		}
 
-		if (toskip && (r = apk_istream_read(is, NULL, toskip)) < 0)
+		if (toskip && (r = apk_istream_skip(is, toskip)) < 0)
 			goto err;
 	}