From a9bf4aae2bdca2c139f482c3f0e098fe6ece1ee0 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 22 Aug 2017 01:46:48 -0700 Subject: [PATCH] Misc fixes to siol (#8262) * Fix onIterMap (divide-and-conquer like USACO Shaping Regions), check return values of every `op` call * Change return types of r_io_read_at and friends back to `int` * Fix some analysis tests and others * Fix mem leaks --- binr/radiff2/radiff2.c | 2 +- libr/anal/fcn.c | 10 +- libr/core/canal.c | 15 +-- libr/core/cio.c | 22 ++--- libr/core/cmd_anal.c | 3 +- libr/core/cmd_cmp.c | 2 +- libr/core/cmd_debug.c | 3 +- libr/core/cmd_section.c | 4 +- libr/core/cmd_zign.c | 2 +- libr/core/core.c | 4 +- libr/core/yank.c | 3 +- libr/include/r_core.h | 4 +- libr/include/r_io.h | 22 +++-- libr/io/cache.c | 14 +-- libr/io/desc.c | 1 + libr/io/io.c | 212 ++++++++++++++++++---------------------- libr/io/ioutils.c | 4 +- libr/io/map.c | 14 ++- libr/io/section.c | 16 ++- 19 files changed, 163 insertions(+), 194 deletions(-) diff --git a/binr/radiff2/radiff2.c b/binr/radiff2/radiff2.c index 7beec61940..73db742bca 100644 --- a/binr/radiff2/radiff2.c +++ b/binr/radiff2/radiff2.c @@ -418,7 +418,7 @@ static ut8 *slurp(RCore **c, const char *file, int *sz) { size = r_io_size (io); if (size > 0 && size < ST32_MAX) { data = calloc (1, size); - if (r_io_read_at (io, 0, data, size)) { + if (r_io_read_all_at (io, 0, data, size)) { if (sz) { *sz = size; } diff --git a/libr/anal/fcn.c b/libr/anal/fcn.c index 55a479e581..845fe3cb49 100644 --- a/libr/anal/fcn.c +++ b/libr/anal/fcn.c @@ -872,16 +872,12 @@ repeat: { bool must_eob = anal->opt.eobjmp; if (!must_eob) { - RIOSection *s = NULL; - SdbList *secs = anal->iob.sections_vget (anal->iob.io, addr); + SdbList *secs = anal->iob.sections_vget (anal->iob.io, addr); if (secs) { - s = (RIOSection *) ls_pop (secs); + RIOSection *s = (RIOSection *) ls_pop (secs); secs->free = NULL; ls_free (secs); - } - if (s) { - must_eob = (s->vaddr <= op.jump); - must_eob &= ((s->vaddr + s->vsize) > op.jump); + must_eob = !(s->vaddr <= op.jump && op.jump < s->vaddr + s->vsize); } } if (must_eob) { diff --git a/libr/core/canal.c b/libr/core/canal.c index 7e8e82e55b..03ad7f6d63 100644 --- a/libr/core/canal.c +++ b/libr/core/canal.c @@ -516,14 +516,17 @@ static int core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int depth RAnalRef *ref; int delta = r_anal_fcn_size (fcn); // XXX hack slow check io error - if (!r_io_read_at (core->io, at + delta, buf, buflen)) { - eprintf ("read errro\n"); + if (!r_io_read_all_at (core->io, at + delta, buf, 4)) { + eprintf ("read error\n"); goto error; } // real read. // this is unnecessary if its contiguous - buflen = r_io_read_at (core->io, at+delta, buf, core->anal->opt.bb_max_size) ? - core->anal->opt.bb_max_size : 0; + buflen = r_io_read_at (core->io, at+delta, buf, core->anal->opt.bb_max_size); + if (buflen < 0) { + eprintf ("read error\n"); + goto error; + } if (core->io->va) { if (!r_io_is_valid_section_offset (core->io, at+delta, !core->anal->opt.noncode)) { goto error; @@ -3367,7 +3370,7 @@ static int esilbreak_mem_read(RAnalEsil *esil, ut64 addr, ut8 *buf, int len) { ut8 buf[8]; ut64 refptr; if (len == 8) { - if (!r_io_read_at (mycore->io, addr, (ut8*)buf, sizeof (buf))) { + if (!r_io_read_all_at (mycore->io, addr, (ut8*)buf, len)) { /* invalid read */ refptr = UT64_MAX; } else { @@ -3375,7 +3378,7 @@ static int esilbreak_mem_read(RAnalEsil *esil, ut64 addr, ut8 *buf, int len) { esilbreak_last_data = refptr; } } else { - if (!r_io_read_at (mycore->io, addr, (ut8*)buf, sizeof (buf))) { + if (!r_io_read_all_at (mycore->io, addr, (ut8*)buf, len)) { /* invalid read */ refptr = UT64_MAX; } else { diff --git a/libr/core/cio.c b/libr/core/cio.c index f36112814a..a2ad753a42 100644 --- a/libr/core/cio.c +++ b/libr/core/cio.c @@ -280,7 +280,7 @@ R_API bool r_core_seek(RCore *core, ut64 addr, bool rb) { if (rb) { r_core_block_read (core); } - return (core->offset != addr); + return core->offset == addr; } R_API int r_core_seek_delta(RCore *core, st64 addr) { @@ -309,13 +309,12 @@ R_API int r_core_seek_delta(RCore *core, st64 addr) { return ret; } -R_API bool r_core_write_at(RCore *core, ut64 addr, const ut8 *buf, int size) { - bool ret; +R_API int r_core_write_at(RCore *core, ut64 addr, const ut8 *buf, int size) { if (!core) { return false; } - ret = r_io_write_at (core->io, addr, buf, size); - if (addr >= core->offset && addr <= core->offset + core->blocksize) { + int ret = r_io_write_at (core->io, addr, buf, size); + if (core->offset <= addr && addr < core->offset + core->blocksize) { r_core_block_read (core); } return ret; @@ -397,18 +396,9 @@ R_API int r_core_block_read(RCore *core) { return -1; } -R_API bool r_core_read_at(RCore *core, ut64 addr, ut8 *buf, int size) { +R_API int r_core_read_at(RCore *core, ut64 addr, ut8 *buf, int size) { if (core) { return r_io_read_at (core->io, addr, buf, size); } - return false; -} - -R_API int r_core_is_valid_offset (RCore *core, ut64 offset) { - if (!core) { - eprintf ("r_core_is_valid_offset: core is NULL\n"); - r_sys_backtrace (); - return R_FAIL; - } - return r_io_is_valid_real_offset (core->io, offset, 0); + return -1; } diff --git a/libr/core/cmd_anal.c b/libr/core/cmd_anal.c index ed14502a0c..7e455bcacd 100644 --- a/libr/core/cmd_anal.c +++ b/libr/core/cmd_anal.c @@ -2899,8 +2899,7 @@ repeat: goto out_return_one; } } - int rc = r_io_read_at (core->io, addr, code, sizeof (code)); - if (!rc) { + if (!r_io_read_all_at (core->io, addr, code, sizeof (code))) { eprintf ("read error\n"); } // TODO: sometimes this is dupe diff --git a/libr/core/cmd_cmp.c b/libr/core/cmd_cmp.c index bab29e84a4..e7c0653c28 100644 --- a/libr/core/cmd_cmp.c +++ b/libr/core/cmd_cmp.c @@ -479,7 +479,7 @@ static int cmd_cmp(void *data, const char *input) { case 'X': buf = malloc (core->blocksize); if (buf) { - if (!r_io_read_at (core->io, r_num_math (core->num, + if (!r_io_read_all_at (core->io, r_num_math (core->num, input + 1), buf, core->blocksize)) { eprintf ("Cannot read hexdump\n"); } else { diff --git a/libr/core/cmd_debug.c b/libr/core/cmd_debug.c index ad24a54ea3..f8d9e91f42 100644 --- a/libr/core/cmd_debug.c +++ b/libr/core/cmd_debug.c @@ -1333,8 +1333,7 @@ static void get_hash_debug_file(const char *path, char *hash, int hash_len) { } r_list_foreach (sects, iter, s) { if (strstr (s->name, ".note.gnu.build-id")) { - err = r_io_read_at (core->io, s->vaddr + 16, (ut8 *) buf, 20); - if (!err) { + if (!r_io_read_all_at (core->io, s->vaddr + 16, (ut8 *) buf, 20)) { eprintf ("Unable to read from memory\n"); goto out_error; } diff --git a/libr/core/cmd_section.c b/libr/core/cmd_section.c index c3a9d68c30..c4b8198c15 100644 --- a/libr/core/cmd_section.c +++ b/libr/core/cmd_section.c @@ -57,7 +57,7 @@ static void __section_list (RIO *io, ut64 offset, RPrint *print, int rad) { ls_foreach (io->sections, iter, s) { char *n = strdup (s->name); r_name_filter (n, strlen (n)); - print->cb_printf ("f section.%s %"PFMT64d" 0x%"PFMT64x"\n", n, s->vaddr, s->vsize); + print->cb_printf ("f section.%s %"PFMT64d" 0x%"PFMT64x"\n", n, s->size, s->vaddr); print->cb_printf ("S 0x%08"PFMT64x" 0x%08"PFMT64x" 0x%08" PFMT64x" 0x%08"PFMT64x" %s %s\n", s->paddr, s->vaddr, s->size, s->vsize, n, r_str_rwx_i (s->flags)); @@ -124,7 +124,7 @@ static bool dumpSectionToDisk(RCore *core, char *file) { } ut64 o = core->offset; if (core->io->va || core->io->debug) { - s = r_io_section_vget (core->io, o); + s = r_io_section_vget (core->io, o); o = s ? o - s->vaddr + s->paddr : o; } ls_foreach (core->io->sections, iter, s) { diff --git a/libr/core/cmd_zign.c b/libr/core/cmd_zign.c index a541dd82d2..5e65e5a657 100644 --- a/libr/core/cmd_zign.c +++ b/libr/core/cmd_zign.c @@ -626,7 +626,7 @@ static bool searchRange(RCore *core, ut64 from, ut64 to, bool rad, struct ctxSea break; } rlen = R_MIN (core->blocksize, to - at); - if (!r_io_read_at (core->io, at, buf, rlen)) { + if (!r_io_read_all_at (core->io, at, buf, rlen)) { retval = false; break; } diff --git a/libr/core/core.c b/libr/core/core.c index b9fb6ff17f..2325856615 100644 --- a/libr/core/core.c +++ b/libr/core/core.c @@ -1539,7 +1539,7 @@ static char *r_core_anal_hasrefs_to_depth(RCore *core, ut64 value, int depth) { int len, r; r = r_io_read_at (core->io, value, buf, sizeof (buf)); buf[sizeof (buf) - 1] = 0; - if (r) { + if (r > 0) { switch (is_string (buf, sizeof(buf), &len)) { case 1: r_strbuf_appendf (s, " (%s%s%s)", c, buf, cend); @@ -2389,7 +2389,7 @@ R_API int r_core_search_cb(RCore *core, ut64 from, ut64 to, RCoreSearchCallback if (delta < len) { len = (int)delta; } - if (!r_io_read_at (core->io, from, buf, len)) { + if (r_io_read_at (core->io, from, buf, len) < 0) { // XXX eprintf ("Cannot read at 0x%"PFMT64x"\n", from); break; } diff --git a/libr/core/yank.c b/libr/core/yank.c index 7486ca7ec9..98592985ce 100644 --- a/libr/core/yank.c +++ b/libr/core/yank.c @@ -78,7 +78,8 @@ static int perform_mapped_file_yank(RCore *core, ut64 offset, ut64 len, const ch ut8 *buf = NULL; if (actual_len > 0 && res == addr) { buf = malloc (actual_len); - if (!r_io_read_at (core->io, addr, buf, actual_len)) { + actual_len = r_io_read_at (core->io, addr, buf, actual_len); + if ((st64)actual_len < 0) { actual_len = 0; } r_core_yank_set (core, R_CORE_FOREIGN_ADDR, buf, len); diff --git a/libr/include/r_core.h b/libr/include/r_core.h index 8baa679b5a..342aec7698 100644 --- a/libr/include/r_core.h +++ b/libr/include/r_core.h @@ -246,7 +246,7 @@ R_API int r_core_seek_align(RCore *core, ut64 align, int count); R_API void r_core_seek_archbits (RCore *core, ut64 addr); R_API int r_core_block_read(RCore *core); R_API int r_core_block_size(RCore *core, int bsize); -R_API bool r_core_read_at(RCore *core, ut64 addr, ut8 *buf, int size); +R_API int r_core_read_at(RCore *core, ut64 addr, ut8 *buf, int size); R_API int r_core_is_valid_offset (RCore *core, ut64 offset); R_API int r_core_shift_block(RCore *core, ut64 addr, ut64 b_size, st64 dist); R_API void r_core_visual_prompt_input (RCore *core); @@ -305,7 +305,7 @@ R_API int r_core_file_binlist(RCore *core); R_API int r_core_file_bin_raise(RCore *core, ut32 num); R_API int r_core_seek_delta(RCore *core, st64 addr); R_API int r_core_extend_at(RCore *core, ut64 addr, int size); -R_API bool r_core_write_at(RCore *core, ut64 addr, const ut8 *buf, int size); +R_API int r_core_write_at(RCore *core, ut64 addr, const ut8 *buf, int size); R_API int r_core_write_op(RCore *core, const char *arg, char op); R_API int r_core_set_file_by_fd (RCore * core, ut64 bin_fd); R_API int r_core_set_file_by_name (RBin * bin, const char * name); diff --git a/libr/include/r_io.h b/libr/include/r_io.h index 0fc93e32c0..95dec9149f 100644 --- a/libr/include/r_io.h +++ b/libr/include/r_io.h @@ -201,8 +201,8 @@ typedef ut64 (*RIODescSize) (RIODesc *desc); typedef RIODesc *(*RIOOpen) (RIO *io, const char *uri, int flags, int mode); typedef RIODesc *(*RIOOpenAt) (RIO *io, const char *uri, int flags, int mode, ut64 at); typedef bool (*RIOClose) (RIO *io, int fd); -typedef bool (*RIOReadAt) (RIO *io, ut64 addr, ut8 *buf, int len); -typedef bool (*RIOWriteAt) (RIO *io, ut64 addr, const ut8 *buf, int len); +typedef int (*RIOReadAt) (RIO *io, ut64 addr, ut8 *buf, int len); +typedef int (*RIOWriteAt) (RIO *io, ut64 addr, const ut8 *buf, int len); typedef int (*RIOSystem) (RIO *io, const char* cmd); typedef bool (*RIOIsValidOff) (RIO *io, ut64 addr, int hasperm); typedef SdbList *(*RIOSectionVgetSecsAt) (RIO *io, ut64 vaddr); @@ -256,12 +256,14 @@ R_API bool r_io_reopen (RIO *io, int fd, int flags, int mode); R_API int r_io_close_all (RIO *io); R_API int r_io_pread_at (RIO *io, ut64 paddr, ut8 *buf, int len); R_API int r_io_pwrite_at (RIO *io, ut64 paddr, const ut8 *buf, int len); -R_API bool r_io_vread_at (RIO *io, ut64 vaddr, ut8 *buf, int len); -R_API bool r_io_vwrite_at (RIO *io, ut64 vaddr, const ut8 *buf, int len); -R_API bool r_io_read_at (RIO *io, ut64 addr, ut8 *buf, int len); -R_API bool r_io_write_at (RIO *io, ut64 addr, const ut8 *buf, int len); -R_API bool r_io_read (RIO *io, ut8 *buf, int len); -R_API bool r_io_write (RIO *io, ut8 *buf, int len); +R_API int r_io_vread_at (RIO *io, ut64 vaddr, ut8 *buf, int len); +R_API int r_io_vwrite_at (RIO *io, ut64 vaddr, const ut8 *buf, int len); +R_API int r_io_read_at (RIO *io, ut64 addr, ut8 *buf, int len); +R_API int r_io_write_at (RIO *io, ut64 addr, const ut8 *buf, int len); +R_API bool r_io_read_all_at (RIO *io, ut64 addr, ut8 *buf, int len); +R_API bool r_io_write_all_at (RIO *io, ut64 addr, const ut8 *buf, int len); +R_API int r_io_read (RIO *io, ut8 *buf, int len); +R_API int r_io_write (RIO *io, ut8 *buf, int len); R_API ut64 r_io_size (RIO *io); R_API bool r_io_is_listener (RIO *io); R_API int r_io_system (RIO *io, const char* cmd); @@ -336,8 +338,8 @@ R_API void r_io_cache_enable(RIO *io, int read, int write); R_API void r_io_cache_init(RIO *io); R_API int r_io_cache_list(RIO *io, int rad); R_API void r_io_cache_reset(RIO *io, int set); -R_API bool r_io_cache_write(RIO *io, ut64 addr, const ut8 *buf, int len); -R_API bool r_io_cache_read(RIO *io, ut64 addr, ut8 *buf, int len); +R_API int r_io_cache_write(RIO *io, ut64 addr, const ut8 *buf, int len); +R_API int r_io_cache_read(RIO *io, ut64 addr, ut8 *buf, int len); /* io/section.c */ R_API void r_io_section_init (RIO *io); diff --git a/libr/io/cache.c b/libr/io/cache.c index 4860a7d9ac..7fa9bb101d 100644 --- a/libr/io/cache.c +++ b/libr/io/cache.c @@ -118,32 +118,32 @@ R_API int r_io_cache_list(RIO *io, int rad) { return false; } -R_API bool r_io_cache_write(RIO *io, ut64 addr, const ut8 *buf, int len) { +R_API int r_io_cache_write(RIO *io, ut64 addr, const ut8 *buf, int len) { RIOCache *ch; ch = R_NEW0 (RIOCache); if (!ch) { - return false; + return -1; } ch->from = addr; ch->to = addr + len; ch->size = len; ch->odata = (ut8*)calloc (1, len + 1); if (!ch->odata) { - return false; + return -1; } ch->data = (ut8*)calloc (1, len + 1); if (!ch->data) { free (ch->odata); - return false; + return -1; } ch->written = io->cached? false: true; r_io_read_at (io, addr, ch->odata, len); memcpy (ch->data, buf, len); r_list_append (io->cache, ch); - return true; + return len; } -R_API bool r_io_cache_read(RIO *io, ut64 addr, ut8 *buf, int len) { +R_API int r_io_cache_read(RIO *io, ut64 addr, ut8 *buf, int len) { int l, covered = 0; RListIter *iter; RIOCache *c; @@ -159,5 +159,5 @@ R_API bool r_io_cache_read(RIO *io, ut64 addr, ut8 *buf, int len) { covered += l; } } - return (covered == 0) ? false: true; + return covered; } diff --git a/libr/io/desc.c b/libr/io/desc.c index 03c1e82662..7975571f5c 100644 --- a/libr/io/desc.c +++ b/libr/io/desc.c @@ -283,6 +283,7 @@ static bool desc_fini_cb(void* user, void* data, ut32 id) { if (desc->plugin && desc->plugin->close) { desc->plugin->close (desc); } + r_io_desc_free (desc); return true; } diff --git a/libr/io/io.c b/libr/io/io.c index d00468671e..50e7ffecb9 100644 --- a/libr/io/io.c +++ b/libr/io/io.c @@ -6,83 +6,48 @@ R_LIB_VERSION (r_io); -typedef int (*cbOnIterMap) (RIO *io, int fd, ut64 addr, ut8*buf, int len); -static void onIterMap(SdbListIter* iter, RIO* io, ut64 vaddr, ut8* buf, - int len, int match_flg, cbOnIterMap op) { - RIOMap* map; - // TODO closed interval [vaddr, vendaddr] is used, this is cumbersome and should be refactored later - ut64 vendaddr; - if (!io || !buf || len < 1) { - return; - } - if (!iter) { - // end of list - if (io->desc) { - op (io, io->desc->fd ,vaddr, buf, len); - } - return; - } - // this block is not that much elegant - if (UT64_ADD_OVFCHK (len - 1, vaddr)) { - // needed for edge-cases - int nlen; - // add a test for this block - vendaddr = UT64_MAX; - nlen = (int) (UT64_MAX - vaddr + 1); - onIterMap (iter->p, io, 0LL, buf + nlen, len - nlen, match_flg, op); - } else { - vendaddr = vaddr + len - 1; - } - map = (RIOMap*) iter->data; - // search for next map or end of list - while (!(map->from <= vendaddr && vaddr < map->to)) { - iter = iter->p; - // end of list - if (!iter) { - if (io->desc) { - op (io, io->desc->fd, vaddr, buf, len); +typedef int (*cbOnIterMap) (RIO *io, int fd, ut64 vaddr, ut8 *buf, int len); +static int onIterMap(SdbListIter *iter, RIO *io, ut64 vaddr, ut8 *buf, + int len, int match_flg, cbOnIterMap op) { + ut64 vendaddr = vaddr + len; + int t, ret = 0; + for (; iter; iter = iter->p) { + RIOMap *map = (RIOMap *)iter->data; + if (vaddr < map->to && map->from < vendaddr) { + if ((map->flags & match_flg) == match_flg || io->p_cache) { + RIODesc *desc = io->desc; + r_io_use_fd (io, map->fd); + t = vaddr < map->from + ? op (io, map->fd, map->delta, buf + map->from - vaddr, + R_MIN (vendaddr - map->from, map->to - map->from)) + : op (io, map->fd, map->delta + vaddr - map->from, buf, + R_MIN (map->to - vaddr, len)); + io->desc = desc; + if (t < 0) { + return t; + } + ret += t; } - return; - } - map = (RIOMap*) iter->data; - } - if (map->from >= vaddr) { - onIterMap (iter->p, io, vaddr, buf, (int) (map->from - vaddr), match_flg, op); - buf = buf + (map->from - vaddr); - vaddr = map->from; - len = (int) (vendaddr - vaddr + 1); - if (vendaddr < map->to) { - if (((map->flags & match_flg) == match_flg) || io->p_cache) { - op (io, map->fd ,map->delta, buf, len); + if (vaddr < map->from) { + t = onIterMap (iter->p, io, vaddr, buf, map->from - vaddr, match_flg, op); + if (t < 0) { + return t; + } + ret += t; } - } else { - if (((map->flags & match_flg) == match_flg) || io->p_cache) { - op (io, map->fd, map->delta, buf, len - (int) (vendaddr - map->to + 1)); + if (map->to < vendaddr) { + t = onIterMap (iter->p, io, map->to, buf + map->to - vaddr, vendaddr - map->to, match_flg, op); + if (t < 0) { + return t; + } + ret += t; } - vaddr = map->to; - buf = buf + (len - (int) (vendaddr - map->to + 1)); - len = (int) (vendaddr - map->to + 1); - onIterMap (iter->p, io, vaddr, buf, len, match_flg, op); - } - } else { - if (vendaddr < map->to) { - if (((map->flags & match_flg) == match_flg) || io->p_cache) { - //warning: may overflow in rare usecases - op (io, map->fd, map->delta + (vaddr - map->from), buf, len); - } - } else { - if (((map->flags & match_flg) == match_flg) || io->p_cache) { - op (io, map->fd, map->delta + (vaddr - map->from), buf, len - (int) (vendaddr - map->to + 1)); - } - vaddr = map->to; - buf = buf + (len - (int) (vendaddr - map->to + 1)); - len = (int) (vendaddr - map->to + 1); - onIterMap (iter->p, io, vaddr, buf, len, match_flg, op); + break; } } + return ret; } - R_API RIO* r_io_new() { return r_io_init (R_NEW0 (RIO)); } @@ -274,72 +239,73 @@ R_API int r_io_pwrite_at(RIO* io, ut64 paddr, const ut8* buf, int len) { return r_io_desc_write_at (io->desc, paddr, buf, len); } -R_API bool r_io_vread_at(RIO* io, ut64 vaddr, ut8* buf, int len) { - if (!io || !buf || (len < 1)) { - return false; +R_API int r_io_vread_at(RIO* io, ut64 vaddr, ut8* buf, int len) { + if (!io || !buf || len < 0) { + return -1; } if (io->ff) { memset (buf, 0xff, len); } r_io_map_cleanup (io); if (!io->maps) { - return !!r_io_pread_at (io, vaddr, buf, len); + return r_io_pread_at (io, vaddr, buf, len); } - onIterMap (io->maps->tail, io, vaddr, buf, len, R_IO_READ, r_io_fd_read_at); - return true; //rethink the return value, we should keep track of succes on onIterMap + if (io->ff) { + memset (buf, 0xff, len); + } + return onIterMap (io->maps->tail, io, vaddr, buf, len, R_IO_READ, r_io_fd_read_at); } -R_API bool r_io_vwrite_at(RIO* io, ut64 vaddr, const ut8* buf, int len) { - if (!io || !buf || (len < 1)) { - return false; +R_API int r_io_vwrite_at(RIO* io, ut64 vaddr, const ut8* buf, int len) { + if (!io || !buf || len < 0) { + return -1; } r_io_map_cleanup (io); if (!io->maps) { - return !!r_io_pwrite_at (io, vaddr, buf, len); + return r_io_pwrite_at (io, vaddr, buf, len); } - onIterMap (io->maps->tail, io, vaddr, (ut8*)buf, len, R_IO_WRITE, (cbOnIterMap)r_io_fd_write_at); - return true; //rethink the return value, we should keep track of succes on onIterMap + return onIterMap (io->maps->tail, io, vaddr, (ut8*)buf, len, R_IO_WRITE, (cbOnIterMap)r_io_fd_write_at); } -R_API bool r_io_read_at(RIO* io, ut64 addr, ut8* buf, int len) { - bool ret; - if (!io || !buf || len < 1) { - return false; +R_API int r_io_read_at(RIO* io, ut64 addr, ut8* buf, int len) { + if (!io || !buf || len < 0) { + return -1; } if (io->buffer_enabled) { - return !!r_io_buffer_read (io, addr, buf, len); - } - if (io->va) { - ret = r_io_vread_at (io, addr, buf, len); - } else { - ret = !!r_io_pread_at (io, addr, buf, len) > 0; + return r_io_buffer_read (io, addr, buf, len); } + int ret = io->va + ? r_io_vread_at (io, addr, buf, len) + : r_io_pread_at (io, addr, buf, len); if (io->cached_read) { - ret &= !!r_io_cache_read (io, addr, buf, len); + (void)r_io_cache_read (io, addr, buf, len); } return ret; } -R_API bool r_io_write_at(RIO* io, ut64 addr, const ut8* buf, int len) { - int i; - bool ret; +R_API bool r_io_read_all_at(RIO* io, ut64 addr, ut8* buf, int len) { + return r_io_read_at (io, addr, buf, len) == len; +} + +R_API int r_io_write_at(RIO* io, ut64 addr, const ut8* buf, int len) { + int i, ret = 0; ut8 *mybuf = (ut8*)buf; - if (!io || !buf || len < 1) { - return false; + if (!io || !buf || len < 0) { + return -1; } if (io->write_mask) { mybuf = r_mem_dup ((void*)buf, len); for (i = 0; i < len; i++) { //this sucks - mybuf[i] &= io->write_mask[i % io->write_mask_len]; + mybuf[i] &= io->write_mask[i % io->write_mask_len]; } } if (io->cached) { - ret = !!r_io_cache_write (io, addr, mybuf, len); + ret = r_io_cache_write (io, addr, mybuf, len); } else if (io->va) { ret = r_io_vwrite_at (io, addr, mybuf, len); } else { - ret = !!r_io_pwrite_at (io, addr, mybuf, len); + ret = r_io_pwrite_at (io, addr, mybuf, len); } if (buf != mybuf) { free (mybuf); @@ -347,26 +313,30 @@ R_API bool r_io_write_at(RIO* io, ut64 addr, const ut8* buf, int len) { return ret; } -R_API bool r_io_read(RIO* io, ut8* buf, int len) { - if (!io) { - return false; - } - if (r_io_read_at (io, io->off, buf, len)) { - io->off += len; - return true; - } - return false; +R_API bool r_io_write_all_at(RIO* io, ut64 addr, const ut8* buf, int len) { + return r_io_write_at (io, addr, buf, len) == len; } -R_API bool r_io_write(RIO* io, ut8* buf, int len) { - if (!io || !buf || len < 1) { - return false; +R_API int r_io_read(RIO* io, ut8* buf, int len) { + if (!io) { + return -1; } - if (r_io_write_at (io, io->off, buf, len)) { - io->off += len; - return true; + int ret = r_io_read_at (io, io->off, buf, len); + if (ret > 0) { + io->off += ret; } - return false; + return ret; +} + +R_API int r_io_write(RIO* io, ut8* buf, int len) { + if (!io) { + return -1; + } + int ret = r_io_write_at (io, io->off, buf, len); + if (ret > 0) { + io->off += ret; + } + return ret; } R_API ut64 r_io_size(RIO* io) { @@ -527,8 +497,9 @@ R_API int r_io_create(RIO* io, const char* file, int mode, int type) { R_API ut64 r_io_seek(RIO* io, ut64 offset, int whence) { if (!io) { - return 0LL; + return -1; } + ut64 t; switch (whence) { case R_IO_SEEK_SET: io->off = offset; @@ -538,7 +509,10 @@ R_API ut64 r_io_seek(RIO* io, ut64 offset, int whence) { break; case R_IO_SEEK_END: default: - io->off = UT64_MAX; + if (!io->desc || (t = r_io_desc_size (io->desc)) == -1) { + return -1; + } + io->off = t + offset; break; } return io->off; diff --git a/libr/io/ioutils.c b/libr/io/ioutils.c index b14460ff55..5e3b5b9eff 100644 --- a/libr/io/ioutils.c +++ b/libr/io/ioutils.c @@ -47,7 +47,7 @@ R_API bool r_io_read_i(RIO* io, ut64 addr, ut64 *val, int size, bool endian) { return false; } size = R_DIM (size, 1, 8); - if (!r_io_read_at (io, addr, buf, size)) { + if (r_io_read_at (io, addr, buf, size) != size) { return false; } *val = r_read_ble (buf, endian, size); @@ -62,7 +62,7 @@ R_API bool r_io_write_i(RIO* io, ut64 addr, ut64 *val, int size, bool endian) { } size = R_DIM (size, 1, 8); r_write_ble (buf, *val, endian, size); - if (!r_io_write_at (io, addr, buf, size)) { + if (r_io_write_at (io, addr, buf, size) != size) { return false; } return true; diff --git a/libr/io/map.c b/libr/io/map.c index 0f2751c9ea..67c194e721 100644 --- a/libr/io/map.c +++ b/libr/io/map.c @@ -9,7 +9,7 @@ R_API RIOMap* r_io_map_new(RIO* io, int fd, int flags, ut64 delta, ut64 addr, ut64 size) { RIOMap* map = NULL; - if (!size || !io || !io->maps || ((UT64_MAX - size + 1) < addr) || !io->map_ids) { + if (!io || !io->maps || UT64_ADD_OVFCHK (size, addr) || !io->map_ids) { return NULL; } map = R_NEW0 (RIOMap); @@ -20,7 +20,7 @@ R_API RIOMap* r_io_map_new(RIO* io, int fd, int flags, ut64 delta, ut64 addr, ut map->fd = fd; map->from = addr; // RIOMap describes an interval of addresses (map->from; map->to) - map->to = addr + size - 1; + map->to = addr + size; map->flags = flags; map->delta = delta; // new map lives on the top, being top the list's tail @@ -99,7 +99,7 @@ R_API RIOMap* r_io_map_get(RIO* io, ut64 addr) { return NULL; } ls_foreach_prev (io->maps, iter, map) { - if ((map->from <= addr) && (map->to >= addr)) { + if (map->from <= addr && addr < map->to) { return map; } } @@ -182,9 +182,7 @@ R_API bool r_io_map_priorize_for_fd(RIO* io, int fd) { ls_delete (io->maps, iter); } } - while (ls_length (list)) { - ls_append (io->maps, ls_pop (list)); - } + ls_join (io->maps, list); ls_free (list); io->maps->free = _map_free; return true; @@ -247,7 +245,7 @@ R_API RIOMap* r_io_map_add_next_available(RIO* io, int fd, int flags, ut64 delta ut64 next_addr = addr, end_addr = next_addr + size; ls_foreach (io->maps, iter, map) { - next_addr = R_MAX (next_addr, map->to + (load_align - (map->to % load_align))); + next_addr = R_MAX (next_addr, map->to + (load_align - (map->to % load_align)) % load_align); // XXX - This does not handle when file overflow 0xFFFFFFFF000 -> 0x00000FFF // adding the check for the map's fd to see if this removes contention for // memory mapping with multiple files. @@ -255,7 +253,7 @@ R_API RIOMap* r_io_map_add_next_available(RIO* io, int fd, int flags, ut64 delta if (map->fd == fd && ((map->from <= next_addr && next_addr < map->to) || (map->from <= end_addr && end_addr < map->to))) { //return r_io_map_add(io, fd, flags, delta, map->to, size); - next_addr = map->to + (load_align - (map->to % load_align)); + next_addr = map->to + (load_align - (map->to % load_align)) % load_align; return r_io_map_add_next_available (io, fd, flags, delta, next_addr, size, load_align); } else { break; diff --git a/libr/io/section.c b/libr/io/section.c index 500814a849..41a4ca11ce 100644 --- a/libr/io/section.c +++ b/libr/io/section.c @@ -54,7 +54,7 @@ RIOSection *_section_chk_dup(RIO *io, ut64 paddr, ut64 vaddr, ut64 size, ut64 vs SdbListIter *iter; char sname[32]; if (!name) { - snprintf (sname, sizeof (sname) - 1, "section.0x016%"PFMT64x "", vaddr); + snprintf (sname, sizeof (sname), "section.0x016%"PFMT64x "", vaddr); } ls_foreach (io->sections, iter, sec) { if ((sec->paddr == paddr) && (sec->vaddr == vaddr) && (sec->size == size) && @@ -79,10 +79,6 @@ R_API RIOSection *r_io_section_add(RIO *io, ut64 paddr, ut64 vaddr, ut64 size, if (!sec) { return NULL; } - if (!r_id_pool_grab_id (io->sec_ids, &sec->id)) { - free (sec); - return NULL; - } sec->paddr = paddr; sec->vaddr = vaddr; sec->size = size; @@ -95,6 +91,15 @@ R_API RIOSection *r_io_section_add(RIO *io, ut64 paddr, ut64 vaddr, ut64 size, } else { sec->name = strdup (name); } + if (!sec->name) { + free (sec); + return NULL; + } + if (!r_id_pool_grab_id (io->sec_ids, &sec->id)) { + free (sec->name); + free (sec); + return NULL; + } ls_append (io->sections, sec); } return sec; @@ -416,6 +421,7 @@ static bool _create_null_map(RIO *io, RIOSection *sec, ut64 at) { } uri = r_str_newf ("null://%"PFMT64u "", sec->vsize - sec->size); desc = r_io_open_at (io, uri, sec->flags, 664, at); + free (uri); if (!desc) { return false; }