Signed-off-by: Alexander Oleinik <alx...@bu.edu> --- migration/qemu-file.c | 84 +++++++++++++++++++++++++++++++++++++++++++ migration/qemu-file.h | 11 ++++++ 2 files changed, 95 insertions(+)
diff --git a/migration/qemu-file.c b/migration/qemu-file.c index 0431585502..453e2897d5 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -786,3 +786,87 @@ void qemu_file_set_blocking(QEMUFile *f, bool block) f->ops->set_blocking(f->opaque, block); } } + +#ifdef CONFIG_FUZZ +#define INCREMENT 10240 +static ssize_t ram_writev_buffer(void *opaque, struct iovec *iov, int iovcnt, + int64_t pos) +{ + ram_disk *rd = (ram_disk *)opaque; + gsize newsize; + ssize_t total_size = 0; + int i; + if (!rd->base) { + rd->base = g_malloc(INCREMENT); + rd->len = INCREMENT; + } + for (i = 0; i < iovcnt; i++) { + if (pos + iov[i].iov_len >= rd->len) { + newsize = ((pos + iov[i].iov_len) / INCREMENT + 1) * INCREMENT; + rd->base = g_realloc(rd->base, newsize); + rd->len = newsize; + } + memcpy(rd->base + pos, iov[i].iov_base, iov[i].iov_len); + pos += iov[i].iov_len; + total_size += iov[i].iov_len; + } + return total_size; +} + +static ssize_t ram_get_buffer(void *opaque, uint8_t *buf, int64_t pos, + size_t size) +{ + ram_disk *rd = (ram_disk *)opaque; + if (pos + size > rd->len) { + if (rd->len - pos >= 0) { + memcpy(buf, rd->base + pos, rd->len - pos); + size = rd->len - pos; + } + } else { + memcpy(buf, rd->base + pos, size); + } + return size; +} + +static int ram_fclose(void *opaque) +{ + return 0; +} + +static const QEMUFileOps ram_read_ops = { + .get_buffer = ram_get_buffer, + .close = ram_fclose +}; + +static const QEMUFileOps ram_write_ops = { + .writev_buffer = ram_writev_buffer, + .close = ram_fclose +}; + +QEMUFile *qemu_fopen_ram(ram_disk **return_rd) +{ + ram_disk *rd = g_new0(ram_disk, 1); + *return_rd = rd; + return qemu_fopen_ops(rd, &ram_write_ops); +} + +QEMUFile *qemu_fopen_ro_ram(ram_disk* rd) +{ + return qemu_fopen_ops(rd, &ram_read_ops); +} + +void qemu_freopen_ro_ram(QEMUFile *f) +{ + void *rd = f->opaque; + f->bytes_xfer = 0; + f->xfer_limit = 0; + f->last_error = 0; + f->iovcnt = 0; + f->buf_index = 0; + f->buf_size = 0; + f->pos = 0; + f->ops = &ram_read_ops; + f->opaque = rd; + return; +} +#endif diff --git a/migration/qemu-file.h b/migration/qemu-file.h index 13baf896bd..7048674f1b 100644 --- a/migration/qemu-file.h +++ b/migration/qemu-file.h @@ -177,4 +177,15 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset, void qemu_put_counted_string(QEMUFile *f, const char *name); +#ifdef CONFIG_FUZZ +typedef struct ram_disk { + void *base; + gsize len; +} ram_disk; + +QEMUFile *qemu_fopen_ram(ram_disk **rd); +QEMUFile *qemu_fopen_ro_ram(ram_disk* rd); +void qemu_freopen_ro_ram(QEMUFile *f); +#endif + #endif -- 2.20.1