summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-08-19 12:26:13 +0200
committerPeter Wu <peter@lekensteyn.nl>2014-12-23 13:04:02 +0100
commita13ee331b6521ab0dace50eaf5b921628a54bd60 (patch)
tree675b130a98501761c884105ca20d82795329cb49
parentd3277afee8a01b607f65c358d6ec400e1f717c68 (diff)
downloadqemu-a13ee331b6521ab0dace50eaf5b921628a54bd60.tar.gz
block/dmg: extract processing of resource forks
Besides the offset, also read the resource length. This length is now used in the extracted function to verify the end of the resource fork against "count" from the resource fork. Signed-off-by: Peter Wu <peter@lekensteyn.nl>
-rw-r--r--block/dmg.c95
1 files changed, 61 insertions, 34 deletions
diff --git a/block/dmg.c b/block/dmg.c
index cae78bf3cb..05894eed1a 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -245,41 +245,13 @@ fail:
return ret;
}
-static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
- Error **errp)
+static int dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds,
+ uint64_t info_begin, uint64_t info_length)
{
- BDRVDMGState *s = bs->opaque;
- DmgHeaderState ds;
- uint64_t info_begin, info_end;
- uint32_t count, tmp;
- int64_t offset;
int ret;
-
- bs->read_only = 1;
- s->n_chunks = 0;
- s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
- ds.last_in_offset = 0;
- ds.last_out_offset = 0;
- ds.max_compressed_size = 1;
- ds.max_sectors_per_chunk = 1;
-
- /* read offset of info blocks */
- offset = bdrv_getlength(bs->file);
- if (offset < 0) {
- ret = offset;
- goto fail;
- }
- /* go the beginning of the UDIF trailer */
- offset -= 0x200;
-
- /* offset of resource fork (RsrcForkOffset) */
- ret = read_uint64(bs, offset + 0x28, &info_begin);
- if (ret < 0) {
- goto fail;
- } else if (info_begin == 0) {
- ret = -EINVAL;
- goto fail;
- }
+ uint32_t count, tmp;
+ uint64_t info_end;
+ uint64_t offset;
ret = read_uint32(bs, info_begin, &tmp);
if (ret < 0) {
@@ -296,6 +268,10 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
ret = -EINVAL;
goto fail;
}
+ if (count > info_length) {
+ ret = -EINVAL;
+ goto fail;
+ }
info_end = info_begin + count;
/* begin of mish block */
@@ -312,12 +288,63 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
}
offset += 4;
- ret = dmg_read_mish_block(bs, &ds, offset, count);
+ ret = dmg_read_mish_block(bs, ds, offset, count);
if (ret < 0) {
goto fail;
}
offset += count;
}
+ return 0;
+
+fail:
+ return ret;
+}
+
+static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
+ Error **errp)
+{
+ BDRVDMGState *s = bs->opaque;
+ DmgHeaderState ds;
+ uint64_t rsrc_fork_offset, rsrc_fork_length;
+ int64_t offset;
+ int ret;
+
+ bs->read_only = 1;
+ s->n_chunks = 0;
+ s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
+ ds.last_in_offset = 0;
+ ds.last_out_offset = 0;
+ ds.max_compressed_size = 1;
+ ds.max_sectors_per_chunk = 1;
+
+ /* read offset of info blocks */
+ offset = bdrv_getlength(bs->file);
+ if (offset < 0) {
+ ret = offset;
+ goto fail;
+ }
+ /* go the beginning of the UDIF trailer */
+ offset -= 0x200;
+
+ /* offset of resource fork (RsrcForkOffset) */
+ ret = read_uint64(bs, offset + 0x28, &rsrc_fork_offset);
+ if (ret < 0) {
+ goto fail;
+ }
+ ret = read_uint64(bs, offset + 0x30, &rsrc_fork_length);
+ if (ret < 0) {
+ goto fail;
+ }
+ if (rsrc_fork_offset != 0 && rsrc_fork_length != 0) {
+ ret = dmg_read_resource_fork(bs, &ds,
+ rsrc_fork_offset, rsrc_fork_length);
+ if (ret < 0) {
+ goto fail;
+ }
+ } else {
+ ret = -EINVAL;
+ goto fail;
+ }
/* initialize zlib engine */
s->compressed_chunk = qemu_try_blockalign(bs->file,