io: make apk_istream_get/read() fail on incomplete read
parent
395e92b66e
commit
7e585512f4
|
@ -154,7 +154,7 @@ static int __adb_m_stream(struct adb *db, struct apk_istream *is, uint32_t expec
|
|||
if (IS_ERR(is)) return PTR_ERR(is);
|
||||
|
||||
if (!(expected_schema & ADB_SCHEMA_IMPLIED)) {
|
||||
if ((r = apk_istream_read(is, &db->hdr, sizeof db->hdr)) != sizeof db->hdr) goto err;
|
||||
if ((r = apk_istream_read(is, &db->hdr, sizeof db->hdr)) < 0) goto err;
|
||||
if (db->hdr.magic != htole32(ADB_FORMAT_MAGIC)) {
|
||||
r = -APKE_ADB_HEADER;
|
||||
goto err;
|
||||
|
@ -166,7 +166,7 @@ static int __adb_m_stream(struct adb *db, struct apk_istream *is, uint32_t expec
|
|||
}
|
||||
|
||||
do {
|
||||
r = apk_istream_read(is, &blk, sizeof blk);
|
||||
r = apk_istream_read_max(is, &blk, sizeof blk);
|
||||
if (r == 0) {
|
||||
if (!trusted) r = -APKE_SIGNATURE_UNTRUSTED;
|
||||
else if (!db->adb.ptr) r = -APKE_ADB_BLOCK;
|
||||
|
@ -183,7 +183,7 @@ static int __adb_m_stream(struct adb *db, struct apk_istream *is, uint32_t expec
|
|||
if (!APK_BLOB_IS_NULL(db->adb)) goto bad_msg;
|
||||
db->adb.ptr = malloc(sz);
|
||||
db->adb.len = adb_block_length(&blk);
|
||||
if ((r = apk_istream_read(is, db->adb.ptr, sz)) != sz) goto err;
|
||||
if ((r = apk_istream_read(is, db->adb.ptr, sz)) < 0) goto err;
|
||||
r = cb(db, &blk, apk_istream_from_blob(&seg.is, db->adb));
|
||||
if (r < 0) goto err;
|
||||
continue;
|
||||
|
|
|
@ -92,9 +92,10 @@ static inline struct apk_istream *apk_istream_from_file(int atfd, const char *fi
|
|||
static inline struct apk_istream *apk_istream_from_file_mmap(int atfd, const char *file) { return __apk_istream_from_file(atfd, file, 1); }
|
||||
struct apk_istream *apk_istream_from_fd(int fd);
|
||||
struct apk_istream *apk_istream_from_fd_url_if_modified(int atfd, const char *url, time_t since);
|
||||
static inline int apk_istream_error(struct apk_istream *is, int err) { if (!is->err) is->err = err; return err; }
|
||||
static inline int apk_istream_error(struct apk_istream *is, int err) { if (is->err >= 0 && err) is->err = err; return is->err < 0 ? is->err : 0; }
|
||||
apk_blob_t apk_istream_mmap(struct apk_istream *is);
|
||||
ssize_t apk_istream_read(struct apk_istream *is, void *ptr, size_t size);
|
||||
ssize_t apk_istream_read_max(struct apk_istream *is, void *ptr, size_t size);
|
||||
int apk_istream_read(struct apk_istream *is, void *ptr, size_t size);
|
||||
void *apk_istream_peek(struct apk_istream *is, size_t len);
|
||||
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);
|
||||
|
|
60
src/io.c
60
src/io.c
|
@ -68,7 +68,7 @@ apk_blob_t apk_istream_mmap(struct apk_istream *is)
|
|||
return APK_BLOB_NULL;
|
||||
}
|
||||
|
||||
ssize_t apk_istream_read(struct apk_istream *is, void *ptr, size_t size)
|
||||
ssize_t apk_istream_read_max(struct apk_istream *is, void *ptr, size_t size)
|
||||
{
|
||||
ssize_t left = size, r = 0;
|
||||
|
||||
|
@ -100,12 +100,17 @@ ssize_t apk_istream_read(struct apk_istream *is, void *ptr, size_t size)
|
|||
is->end = is->buf + r;
|
||||
}
|
||||
|
||||
if (r < 0) return r;
|
||||
if (size && left == size && !is->err) is->err = 1;
|
||||
if (size == left) return is->err < 0 ? is->err : 0;
|
||||
if (r < 0) return apk_istream_error(is, r);
|
||||
if (left == size) return apk_istream_error(is, (size && !is->err) ? 1 : 0);
|
||||
return size - left;
|
||||
}
|
||||
|
||||
int apk_istream_read(struct apk_istream *is, void *ptr, size_t size)
|
||||
{
|
||||
ssize_t r = apk_istream_read_max(is, ptr, size);
|
||||
return r == size ? 0 : apk_istream_error(is, -APKE_EOF);
|
||||
}
|
||||
|
||||
static int __apk_istream_fill(struct apk_istream *is)
|
||||
{
|
||||
ssize_t sz;
|
||||
|
@ -117,51 +122,46 @@ static int __apk_istream_fill(struct apk_istream *is)
|
|||
memmove(is->buf, is->ptr, sz);
|
||||
is->ptr = is->buf;
|
||||
is->end = is->buf + sz;
|
||||
}
|
||||
} else if (is->end-is->ptr == is->buf_size)
|
||||
return -ENOBUFS;
|
||||
|
||||
sz = is->ops->read(is, is->end, is->buf + is->buf_size - is->end);
|
||||
if (sz <= 0) {
|
||||
is->err = sz ?: 1;
|
||||
return is->err;
|
||||
}
|
||||
if (sz <= 0) return apk_istream_error(is, sz ?: 1);
|
||||
is->end += sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *apk_istream_peek(struct apk_istream *is, size_t len)
|
||||
{
|
||||
int r;
|
||||
|
||||
do {
|
||||
if (is->end - is->ptr >= len) {
|
||||
void *ptr = is->ptr;
|
||||
return ptr;
|
||||
}
|
||||
} while (!__apk_istream_fill(is));
|
||||
r = __apk_istream_fill(is);
|
||||
} while (r == 0);
|
||||
|
||||
if (is->end-is->ptr == is->buf_size)
|
||||
return ERR_PTR(-ENOBUFS);
|
||||
if (is->err > 0)
|
||||
return ERR_PTR(-APKE_EOF);
|
||||
return ERR_PTR(-EIO);
|
||||
return ERR_PTR(r > 0 ? -APKE_EOF : r);
|
||||
}
|
||||
|
||||
void *apk_istream_get(struct apk_istream *is, size_t len)
|
||||
{
|
||||
void *p = apk_istream_peek(is, len);
|
||||
if (!IS_ERR_OR_NULL(p)) is->ptr += len;
|
||||
else apk_istream_error(is, PTR_ERR(p));
|
||||
return p;
|
||||
}
|
||||
|
||||
int apk_istream_get_max(struct apk_istream *is, size_t max, apk_blob_t *data)
|
||||
{
|
||||
if (is->ptr == is->end)
|
||||
__apk_istream_fill(is);
|
||||
|
||||
if (is->ptr == is->end) __apk_istream_fill(is);
|
||||
if (is->ptr != is->end) {
|
||||
*data = APK_BLOB_PTR_LEN((char*)is->ptr, min((size_t)(is->end - is->ptr), max));
|
||||
is->ptr += data->len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*data = APK_BLOB_NULL;
|
||||
return is->err < 0 ? is->err : -APKE_EOF;
|
||||
}
|
||||
|
@ -169,19 +169,17 @@ int apk_istream_get_max(struct apk_istream *is, size_t max, apk_blob_t *data)
|
|||
int apk_istream_get_delim(struct apk_istream *is, apk_blob_t token, apk_blob_t *data)
|
||||
{
|
||||
apk_blob_t ret = APK_BLOB_NULL, left = APK_BLOB_NULL;
|
||||
int r;
|
||||
|
||||
do {
|
||||
if (apk_blob_split(APK_BLOB_PTR_LEN((char*)is->ptr, is->end - is->ptr), token, &ret, &left))
|
||||
break;
|
||||
if (is->end - is->ptr == is->buf_size) {
|
||||
is->err = -ENOBUFS;
|
||||
break;
|
||||
}
|
||||
} while (!__apk_istream_fill(is));
|
||||
r = __apk_istream_fill(is);
|
||||
} while (r == 0);
|
||||
|
||||
/* Last segment before end-of-file. Return also zero length non-null
|
||||
* blob if eof comes immediately after the delimiter. */
|
||||
if (is->ptr && is->err > 0)
|
||||
if (is->ptr && r > 0)
|
||||
ret = APK_BLOB_PTR_LEN((char*)is->ptr, is->end - is->ptr);
|
||||
|
||||
if (!APK_BLOB_IS_NULL(ret)) {
|
||||
|
@ -190,8 +188,9 @@ int apk_istream_get_delim(struct apk_istream *is, apk_blob_t token, apk_blob_t *
|
|||
*data = ret;
|
||||
return 0;
|
||||
}
|
||||
if (r < 0) apk_istream_error(is, r);
|
||||
*data = APK_BLOB_NULL;
|
||||
return is->err < 0 ? is->err : -APKE_EOF;
|
||||
return r < 0 ? r : -APKE_EOF;
|
||||
}
|
||||
|
||||
static void blob_get_meta(struct apk_istream *is, struct apk_file_meta *meta)
|
||||
|
@ -571,21 +570,16 @@ ssize_t apk_stream_copy(struct apk_istream *is, struct apk_ostream *os, size_t s
|
|||
apk_blob_t apk_blob_from_istream(struct apk_istream *is, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
ssize_t rsize;
|
||||
|
||||
ptr = malloc(size);
|
||||
if (ptr == NULL)
|
||||
return APK_BLOB_NULL;
|
||||
|
||||
rsize = apk_istream_read(is, ptr, size);
|
||||
if (rsize < 0) {
|
||||
if (apk_istream_read(is, ptr, size) < 0) {
|
||||
free(ptr);
|
||||
return APK_BLOB_NULL;
|
||||
}
|
||||
if (rsize != size)
|
||||
ptr = realloc(ptr, rsize);
|
||||
|
||||
return APK_BLOB_PTR_LEN(ptr, rsize);
|
||||
return APK_BLOB_PTR_LEN(ptr, size);
|
||||
}
|
||||
|
||||
apk_blob_t apk_blob_from_file(int atfd, const char *file)
|
||||
|
|
|
@ -141,7 +141,7 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser,
|
|||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
entry.name = buf.name;
|
||||
while ((r = apk_istream_read(is, &buf, 512)) == 512) {
|
||||
while ((r = apk_istream_read_max(is, &buf, 512)) == 512) {
|
||||
if (buf.name[0] == '\0') {
|
||||
if (end) break;
|
||||
end++;
|
||||
|
@ -182,7 +182,7 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser,
|
|||
switch (buf.typeflag) {
|
||||
case 'L': /* GNU long name extension */
|
||||
if ((r = blob_realloc(&longname, entry.size+1)) != 0 ||
|
||||
(r = apk_istream_read(is, longname.ptr, entry.size)) != entry.size)
|
||||
(r = apk_istream_read(is, longname.ptr, entry.size)) < 0)
|
||||
goto err;
|
||||
longname.ptr[entry.size] = 0;
|
||||
entry.name = longname.ptr;
|
||||
|
@ -219,7 +219,7 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser,
|
|||
case 'x': /* file specific pax header */
|
||||
paxlen = entry.size;
|
||||
if ((r = blob_realloc(&pax, (paxlen + 511) & -512)) != 0 ||
|
||||
(r = apk_istream_read(is, pax.ptr, paxlen)) != paxlen)
|
||||
(r = apk_istream_read(is, pax.ptr, paxlen)) < 0)
|
||||
goto err;
|
||||
toskip -= entry.size;
|
||||
break;
|
||||
|
@ -244,14 +244,14 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser,
|
|||
paxlen = 0;
|
||||
}
|
||||
|
||||
if (toskip && (r = apk_istream_read(is, NULL, toskip)) != toskip)
|
||||
if (toskip && (r = apk_istream_read(is, NULL, toskip)) < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Read remaining end-of-archive records, to ensure we read all of
|
||||
* the file. The underlying istream is likely doing checksumming. */
|
||||
if (r == 512) {
|
||||
while ((r = apk_istream_read(is, &buf, 512)) == 512) {
|
||||
while ((r = apk_istream_read_max(is, &buf, 512)) == 512) {
|
||||
if (buf.name[0] != 0) break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -976,23 +976,13 @@ int apk_ipkg_add_script(struct apk_installed_package *ipkg,
|
|||
struct apk_istream *is,
|
||||
unsigned int type, unsigned int size)
|
||||
{
|
||||
void *ptr;
|
||||
int r;
|
||||
apk_blob_t b;
|
||||
|
||||
if (type >= APK_SCRIPT_MAX)
|
||||
return -1;
|
||||
|
||||
ptr = malloc(size);
|
||||
r = apk_istream_read(is, ptr, size);
|
||||
if (r < 0) {
|
||||
free(ptr);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (ipkg->script[type].ptr)
|
||||
free(ipkg->script[type].ptr);
|
||||
ipkg->script[type].ptr = ptr;
|
||||
ipkg->script[type].len = size;
|
||||
if (type >= APK_SCRIPT_MAX) return -1;
|
||||
b = apk_blob_from_istream(is, size);
|
||||
if (APK_BLOB_IS_NULL(b)) return -1;
|
||||
if (ipkg->script[type].ptr) free(ipkg->script[type].ptr);
|
||||
ipkg->script[type] = b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue