Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 27 additions & 63 deletions libr/core/yank.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,71 +18,37 @@ static ut32 consume_chars(const char *input, char b) {
return i;
}

static bool perform_mapped_file_yank(RCore *core, ut64 offset, ut64 len, const char *filename) {
// grab the current file descriptor, so we can reset core and io state
// after our io op is done
RIODesc *yankdesc = NULL;
ut64 fd = core->io->desc ? core->io->desc->fd: -1, yank_file_sz = 0,
loadaddr = 0, addr = offset;
static bool perform_file_yank(RCore *core, ut64 offset, ut64 len, const char *filename) {
if (R_STR_ISEMPTY (filename)) {
return false;
}
const ut64 io_off = core->io->off;
RIODesc *desc = r_io_desc_open (core->io, filename, R_PERM_R, 0644);
if (!desc) {
core->io->off = io_off;
return false;
}
bool res = false;

if (filename && *filename) {
ut64 load_align = r_config_get_i (core->config, "file.loadalign");
RIOMap *map = NULL;
yankdesc = r_io_open_nomap (core->io, filename, R_PERM_R, 0644);
// map the file in for IO operations.
if (yankdesc && load_align) {
yank_file_sz = r_io_size (core->io);
ut64 addr = 0;
r_io_map_locate (core->io, &addr, yank_file_sz, load_align);
map = r_io_map_add (core->io, yankdesc->fd, R_PERM_R, 0, addr, yank_file_sz);
loadaddr = map? r_io_map_begin (map): -1;
if (yankdesc && map && loadaddr != -1) {
// ***NOTE*** this is important, we need to
// address the file at its physical address!
addr += loadaddr;
} else if (yankdesc) {
R_LOG_ERROR ("Unable to map the opened file: %s", filename);
r_io_desc_close (yankdesc);
yankdesc = NULL;
} else {
R_LOG_ERROR ("Unable to open the file: %s", filename);
}
}
const ut64 size = r_io_desc_size (desc);
if (len == UT64_MAX) {
len = size;
}

// if len is -1 then we yank in everything
if (len == -1) {
len = yank_file_sz;
if (!len || len > ST32_MAX || offset > size || len > size - offset) {
R_LOG_ERROR ("Invalid file yank range");
goto beach;
}

// this wont happen if the file failed to open or the file failed to
// map into the IO layer
if (yankdesc) {
ut64 nres = r_io_seek (core->io, addr, R_IO_SEEK_SET);
ut64 actual_len = len <= yank_file_sz? len: 0;
ut8 *buf = NULL;
if (actual_len > 0 && nres == addr) {
buf = malloc (actual_len);
if (!r_io_read_at (core->io, addr, buf, actual_len)) {
free (buf);
buf = NULL;
}
r_core_yank_set (core, R_CORE_FOREIGN_ADDR, buf, len);
res = true;
} else if (nres != addr) {
R_LOG_ERROR ("Unable to yank data from file: (loadaddr (0x%" PFMT64x ") (addr (0x%" PFMT64x ") > file_sz (0x%"PFMT64x ")", nres, addr, yank_file_sz);
} else if (actual_len == 0) {
R_LOG_ERROR ("Unable to yank from file: addr+len (0x%" PFMT64x ") > file_sz (0x%"PFMT64x ")", addr + len, yank_file_sz);
ut8 *buf = malloc (len);
if (buf) {
if (r_io_desc_read_at (desc, offset, buf, len) == len) {
res = r_core_yank_set (core, R_CORE_FOREIGN_ADDR, buf, len);
} else {
R_LOG_ERROR ("Cannot read file for yank: %s", filename);
}
r_io_desc_close (yankdesc);
free (buf);
}
if (fd != -1) {
r_io_use_fd (core->io, fd);
core->switch_file_view = 1;
r_core_block_read (core);
}
beach:
r_io_desc_close (desc);
core->io->off = io_off;
return res;
}

Expand Down Expand Up @@ -405,15 +371,13 @@ R_API bool r_core_yank_file_ex(RCore *core, const char *input) {
}
ut64 addr = r_num_math (core->num, inp + adv);
adv += next + 1;
// grab the current file descriptor, so we can reset core and io state
// after our io op is done
bool b = perform_mapped_file_yank (core, addr, len, inp + adv);
bool b = perform_file_yank (core, addr, len, inp + adv);
free (inp);
return b;
}

R_API bool r_core_yank_file_all(RCore *core, const char *input) {
R_RETURN_VAL_IF_FAIL (core && input, false);
ut64 adv = consume_chars (input, ' ');
return perform_mapped_file_yank (core, 0, -1, input + adv);
return perform_file_yank (core, 0, UT64_MAX, input + adv);
}
26 changes: 9 additions & 17 deletions libr/io/p_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ R_API int r_io_desc_cache_read(RIODesc *desc, ut64 paddr, ut8 *buf, int len) {
}

static void __riocache_free(void *user) {
RIOCache *cache = (RIOCache *) user;
RIOCacheItem *cache = (RIOCacheItem *)user;
free (cache->data);
free (cache->odata);
free (cache);
}

Expand Down Expand Up @@ -236,31 +238,27 @@ static bool __desc_cache_list_cb(void *user, const ut64 k, const void *v) {
}

R_API RList *r_io_desc_cache_list(RIODesc *desc) {
if (!desc || !desc->io || !desc->io->desc || !desc->io->p_cache || !desc->cache) {
if (!desc || !desc->io || !desc->io->p_cache || !desc->cache) {
return NULL;
}
RList *writes = r_list_newf ((RListFree)__riocache_free);
if (!writes) {
return NULL;
}
ht_up_foreach (desc->cache, __desc_cache_list_cb, writes);
RIODesc *current = desc->io->desc;
desc->io->desc = desc;
desc->io->p_cache = false;

RIOCacheItem *c;
RListIter *iter;
r_list_foreach (writes, iter, c) {
const ut64 itvSize = r_itv_size (c->itv);
c->odata = calloc (1, itvSize);
c->odata = malloc (itvSize);
if (!c->odata) {
r_list_free (writes);
return NULL;
}
r_io_pread_at (desc->io, r_itv_begin (c->itv), c->odata, itvSize);
memset (c->odata, desc->io->ff? desc->io->Oxff: 0, itvSize);
r_io_plugin_read_at (desc, r_itv_begin (c->itv), c->odata, itvSize);
}
desc->io->p_cache = true;
desc->io->desc = current;
return writes;
}

Expand All @@ -278,33 +276,27 @@ static bool __desc_cache_commit_cb(void *user, const ut64 k, const void *v) {
buf[i] = dcache->cdata[byteaddr];
i++;
} else if (i > 0) {
r_io_pwrite_at (desc->io, blockaddr + byteaddr - i, buf, i);
r_io_plugin_write_at (desc, blockaddr + byteaddr - i, buf, i);
i = 0;
}
}
if (i > 0) {
r_io_pwrite_at (desc->io, blockaddr + R_IO_DESC_CACHE_SIZE - i, buf, i);
r_io_plugin_write_at (desc, blockaddr + R_IO_DESC_CACHE_SIZE - i, buf, i);
}
return true;
}

R_API bool r_io_desc_cache_commit(RIODesc *desc) {
RIODesc *current;
if (!desc || !(desc->perm & R_PERM_W) || !desc->io ||
!desc->io->files.data || !desc->io->p_cache) {
return false;
}
if (!desc->cache) {
return true;
}
current = desc->io->desc;
desc->io->desc = desc;
desc->io->p_cache = false;
ht_up_foreach (desc->cache, __desc_cache_commit_cb, desc);
ht_up_free (desc->cache);
desc->cache = NULL;
desc->io->p_cache = true;
desc->io->desc = current;
return true;
}

Expand Down
62 changes: 62 additions & 0 deletions test/db/cmd/cmd_yank
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,65 @@ EXPECT=<<EOF
done
EOF
RUN

NAME=file yank reads its own descriptor without changing IO state
FILE=malloc://16
CMDS=<<EOF
wx 11223344
s 8
e file.loadalign=0
yfa hex://aabbccdd
y8
e io.va=false
yf 2 1 hex://aabbccdd
y8
e io.autofd=false
e file.loadalign=0x1000
e io.va=true
yf 2 1 hex://aabbccdd
y8
yfa hex://aabbccdd
y8
oqq
oq~?
om~?
s
p8 4 @ 0
EOF
EXPECT=<<EOF
aabbccdd
bbcc
bbcc
aabbccdd
3
1
1
0x8
11223344
EOF
RUN

NAME=file yank rejects out-of-range reads without replacing the clipboard
FILE=malloc://16
CMDS=<<EOF
ywx 1122
yf 2 3 hex://aabbccdd
yf 1 4 hex://aabbccdd
yf 1 0xffffffffffffffff hex://aabbccdd
yf 0x80000000 0 hex://aabbccdd
y8
oq~?
om~?
EOF
EXPECT=<<EOF
1122
1
1
EOF
EXPECT_ERR=<<EOF
ERROR: Invalid file yank range
ERROR: Invalid file yank range
ERROR: Invalid file yank range
ERROR: Invalid file yank range
EOF
RUN
66 changes: 66 additions & 0 deletions test/db/io/cache
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,69 @@ EXPECT=<<EOF
0000
EOF
RUN

NAME=pcache commit keeps the selected fd and cache mode
FILE=malloc://128
CMDS=<<EOF
e io.va=false
wx 1122
on malloc://128
o=4
wx aabb
e io.pcache=true
wx c0c1
wx fefe @ 0x3f
o=3
wcpi 4
oqq
p8 2 @ 0
o=4
p8 2 @ 0
p8 2 @ 0x3f
wx d0d1
e io.pcache.read=false
p8 2 @ 0
e io.pcache.read=true
p8 2 @ 0
wcpi 4
e io.pcache.read=false
p8 2 @ 0
EOF
EXPECT=<<EOF
3
1122
c0c1
fefe
c0c1
d0d1
d0d1
EOF
RUN

NAME=pcache listing keeps write-only caching and the selected fd
FILE=malloc://128
CMDS=<<EOF
e io.va=false
e log.level=0
wx 1122
on malloc://128
o=4
wx aabb
e io.pcache.write=true
wx c0c1
o=3
wcp 4
oqq
p8 2 @ 0
o=4
p8 2 @ 0
e io.pcache.read=true
p8 2 @ 0
EOF
EXPECT=<<EOF
3
1122
aabb
c0c1
EOF
RUN
Loading