mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-23 13:19:54 +00:00
Improve RBuffer api, start to refactor rbin to use more rbuf ##bin (#12495)
- Added a new rule in the DEVELOPERS.md file
This commit is contained in:
parent
63fae31b1e
commit
7060103292
@ -160,6 +160,21 @@ a = (b << 3) * 5;
|
||||
}
|
||||
```
|
||||
|
||||
* Structure in the C files
|
||||
|
||||
The structure of the C files in r2 must be like this:
|
||||
|
||||
```c
|
||||
/* Copyright ... */ ## copyright
|
||||
#include <r_core.h> ## includes
|
||||
static int globals ## const, define, global variables
|
||||
static void helper() {} ## static functions
|
||||
R_IPI void internal() {} ## internal apis (used only inside the library
|
||||
R_API void public() {} ## public apis starting with constructor/destructor
|
||||
|
||||
```
|
||||
|
||||
|
||||
* Why return int vs enum
|
||||
|
||||
The reason why many places in r2land functions return int instead of an enum type is because enums cant be OR'ed; otherwise, it breaks the usage within a switch statement and swig can't handle that stuff.
|
||||
|
@ -147,13 +147,13 @@ static bool isBinopHelp(const char *op) {
|
||||
}
|
||||
|
||||
static bool extract_binobj(const RBinFile *bf, RBinXtrData *data, int idx) {
|
||||
ut64 bin_size = data ? data->size : 0;
|
||||
ut64 bin_size = data? data->size: 0;
|
||||
ut8 *bytes;
|
||||
const char *xtr_type = "";
|
||||
char *arch = "unknown";
|
||||
int bits = 0;
|
||||
int bits = 0, nb;
|
||||
char *libname = NULL;
|
||||
const char *filename = bf ? bf->file : NULL;
|
||||
const char *filename = bf? bf->file: NULL;
|
||||
char *path = NULL, *ptr = NULL;
|
||||
bool res = false;
|
||||
|
||||
@ -170,11 +170,16 @@ static bool extract_binobj(const RBinFile *bf, RBinXtrData *data, int idx) {
|
||||
eprintf ("This is not a fat bin\n");
|
||||
return false;
|
||||
}
|
||||
bytes = data->buffer;
|
||||
bytes = malloc (bin_size);
|
||||
if (!bytes) {
|
||||
eprintf ("error: BinFile buffer is empty\n");
|
||||
return false;
|
||||
}
|
||||
nb = r_buf_read_at (data->buf, 0, bytes, bin_size);
|
||||
if (nb <= 0) {
|
||||
eprintf ("Couldn't read xtrdata\n");
|
||||
return false;
|
||||
}
|
||||
if (!arch) {
|
||||
arch = "unknown";
|
||||
}
|
||||
@ -212,7 +217,7 @@ static bool extract_binobj(const RBinFile *bf, RBinXtrData *data, int idx) {
|
||||
free (outfile);
|
||||
free (outpath);
|
||||
free (path);
|
||||
R_FREE (data->buffer);
|
||||
free (bytes);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
173
libr/bin/bfile.c
173
libr/bin/bfile.c
@ -259,6 +259,65 @@ static int string_scan_range(RList *list, RBinFile *bf, int min,
|
||||
return count;
|
||||
}
|
||||
|
||||
static int is_data_section(RBinFile *a, RBinSection *s) {
|
||||
if (s->has_strings || s->is_data) {
|
||||
return true;
|
||||
}
|
||||
// Rust
|
||||
return strstr (s->name, "_const") != NULL;
|
||||
}
|
||||
|
||||
static void get_strings_range(RBinFile *bf, RList *list, int min, int raw, ut64 from, ut64 to) {
|
||||
r_return_if_fail (bf && bf->buf);
|
||||
|
||||
RBinPlugin *plugin = r_bin_file_cur_plugin (bf);
|
||||
RBinString *ptr;
|
||||
RListIter *it;
|
||||
|
||||
if (!raw && (!plugin || !plugin->info)) {
|
||||
return;
|
||||
}
|
||||
if (!min) {
|
||||
min = plugin? plugin->minstrlen: 4;
|
||||
}
|
||||
/* Some plugins return zero, fix it up */
|
||||
if (!min) {
|
||||
min = 4;
|
||||
}
|
||||
if (min < 0) {
|
||||
return;
|
||||
}
|
||||
if (!to || to > bf->buf->length) {
|
||||
to = r_buf_size (bf->buf);
|
||||
}
|
||||
if (!to) {
|
||||
return;
|
||||
}
|
||||
if (raw != 2) {
|
||||
ut64 size = to - from;
|
||||
// in case of dump ignore here
|
||||
if (bf->rbin->maxstrbuf && size && size > bf->rbin->maxstrbuf) {
|
||||
if (bf->rbin->verbose) {
|
||||
eprintf ("WARNING: bin_strings buffer is too big (0x%08" PFMT64x "). Use -zzz or set bin.maxstrbuf (RABIN2_MAXSTRBUF) in r2 (rabin2)\n",
|
||||
size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (string_scan_range (list, bf, min, from, to, -1) < 0) {
|
||||
return;
|
||||
}
|
||||
if (bf->o) {
|
||||
r_list_foreach (list, it, ptr) {
|
||||
RBinSection *s = r_bin_get_section_at (bf->o, ptr->paddr, false);
|
||||
if (s) {
|
||||
ptr->vaddr = s->vaddr + (ptr->paddr - s->paddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
R_IPI RBinFile *r_bin_file_new(RBin *bin, const char *file, const ut8 *bytes, ut64 sz, ut64 file_sz, int rawstr, int fd, const char *xtrname, Sdb *sdb, bool steal_ptr) {
|
||||
RBinFile *binfile = R_NEW0 (RBinFile);
|
||||
if (!binfile) {
|
||||
@ -285,7 +344,7 @@ R_IPI RBinFile *r_bin_file_new(RBin *bin, const char *file, const ut8 *bytes, ut
|
||||
binfile->size = file_sz;
|
||||
binfile->xtr_data = r_list_newf ((RListFree)r_bin_xtrdata_free);
|
||||
binfile->objs = r_list_newf ((RListFree)r_bin_object_free);
|
||||
binfile->xtr_obj = NULL;
|
||||
binfile->xtr_obj = NULL;
|
||||
|
||||
if (!binfile->buf) {
|
||||
//r_bin_file_free (binfile);
|
||||
@ -328,32 +387,28 @@ static RBinPlugin *get_plugin(RBin *bin, const char *pluginname, const ut8 *byte
|
||||
return r_bin_get_binplugin_any (bin);
|
||||
}
|
||||
|
||||
static RBinPlugin * get_plugin_with_buffer (RBin *bin, RBuffer *buf) {
|
||||
ut8 bytes[4096];
|
||||
// XXX this must be removed to make get_plugin work with RBuffer instead of char*+sz
|
||||
r_buf_read_at (buf, 0, bytes, sizeof (bytes));
|
||||
return get_plugin (bin, NULL, (const ut8 *)bytes, sizeof (bytes));
|
||||
}
|
||||
|
||||
R_API bool r_bin_file_object_new_from_xtr_data(RBin *bin, RBinFile *bf, ut64 baseaddr, ut64 loadaddr, RBinXtrData *data) {
|
||||
r_return_val_if_fail (bin && bf && data, false);
|
||||
|
||||
RBinObject *o = NULL;
|
||||
RBinPlugin *plugin = NULL;
|
||||
ut8* bytes;
|
||||
ut64 offset = data->offset;
|
||||
ut64 sz = data->size;
|
||||
|
||||
// for right now the bytes used will just be the offest into the binfile
|
||||
// buffer if the extraction requires some sort of transformation then
|
||||
// this will need to be fixed here.
|
||||
bytes = data->buffer;
|
||||
r_return_val_if_fail (bytes, false);
|
||||
RBinPlugin *plugin = get_plugin_with_buffer (bin, data->buf);
|
||||
bf->buf = r_buf_new_with_bufref (data->buf);
|
||||
|
||||
plugin = get_plugin (bin, NULL, (const ut8 *)bytes, sz);
|
||||
|
||||
r_buf_free (bf->buf);
|
||||
bf->buf = r_buf_new_with_bytes ((const ut8 *)bytes, data->size);
|
||||
// r_bin_object_new append the new object into binfile
|
||||
o = r_bin_object_new (bf, plugin, baseaddr, loadaddr, offset, sz);
|
||||
// size is set here because the reported size of the object depends on
|
||||
// if loaded from xtr plugin or partially read
|
||||
RBinObject *o = r_bin_object_new (bf, plugin, baseaddr, loadaddr, offset, sz);
|
||||
if (!o) {
|
||||
return false;
|
||||
}
|
||||
// size is set here because the reported size of the object depends on
|
||||
// if loaded from xtr plugin or partially read
|
||||
if (!o->size) {
|
||||
o->size = sz;
|
||||
}
|
||||
@ -376,14 +431,23 @@ R_API bool r_bin_file_object_new_from_xtr_data(RBin *bin, RBinFile *bf, ut64 bas
|
||||
}
|
||||
|
||||
static RBinFile *file_create_append(RBin *bin, const char *file, const ut8 *bytes, ut64 sz, ut64 file_sz, int rawstr, int fd, const char *xtrname, bool steal_ptr) {
|
||||
RBinFile *bf = r_bin_file_new (bin, file, bytes, sz, file_sz, rawstr,
|
||||
fd, xtrname, bin->sdb, steal_ptr);
|
||||
RBinFile *bf = r_bin_file_new (bin, file, bytes, sz, file_sz, rawstr, fd, xtrname, bin->sdb, steal_ptr);
|
||||
if (bf) {
|
||||
r_list_append (bin->binfiles, bf);
|
||||
}
|
||||
return bf;
|
||||
}
|
||||
|
||||
static bool xtr_metadata_match(RBinXtrData *xtr_data, const char *arch, int bits) {
|
||||
if (!xtr_data->metadata || !xtr_data->metadata->arch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char *iter_arch = xtr_data->metadata->arch;
|
||||
int iter_bits = xtr_data->metadata->bits;
|
||||
return bits == iter_bits && !strcmp (iter_arch, arch) && !xtr_data->loaded;
|
||||
}
|
||||
|
||||
R_IPI RBinFile *r_bin_file_new_from_bytes(RBin *bin, const char *file, const ut8 *bytes, ut64 sz, ut64 file_sz, int rawstr, ut64 baseaddr, ut64 loadaddr, int fd, const char *pluginname, ut64 offset) {
|
||||
r_return_val_if_fail (sz != UT64_MAX, NULL);
|
||||
|
||||
@ -403,20 +467,9 @@ R_IPI RBinFile *r_bin_file_new_from_bytes(RBin *bin, const char *file, const ut8
|
||||
if (!o->size) {
|
||||
o->size = file_sz;
|
||||
}
|
||||
|
||||
return bf;
|
||||
}
|
||||
|
||||
static bool xtr_metadata_match(RBinXtrData *xtr_data, const char *arch, int bits) {
|
||||
if (!xtr_data->metadata || !xtr_data->metadata->arch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char *iter_arch = xtr_data->metadata->arch;
|
||||
int iter_bits = xtr_data->metadata->bits;
|
||||
return bits == iter_bits && !strcmp (iter_arch, arch) && !xtr_data->loaded;
|
||||
}
|
||||
|
||||
R_API RBinFile *r_bin_file_find_by_arch_bits(RBin *bin, const char *arch, int bits) {
|
||||
RListIter *iter;
|
||||
RBinFile *binfile = NULL;
|
||||
@ -698,66 +751,6 @@ R_API RBinPlugin *r_bin_file_cur_plugin(RBinFile *binfile) {
|
||||
return (binfile && binfile->o)? binfile->o->plugin: NULL;
|
||||
}
|
||||
|
||||
static int is_data_section(RBinFile *a, RBinSection *s) {
|
||||
if (s->has_strings || s->is_data) {
|
||||
return true;
|
||||
}
|
||||
// Rust
|
||||
return strstr (s->name, "_const") != NULL;
|
||||
}
|
||||
|
||||
static void get_strings_range(RBinFile *bf, RList *list, int min, int raw, ut64 from, ut64 to) {
|
||||
r_return_if_fail (bf && bf->buf);
|
||||
|
||||
RBinPlugin *plugin = r_bin_file_cur_plugin (bf);
|
||||
RBinString *ptr;
|
||||
RListIter *it;
|
||||
|
||||
if (!raw) {
|
||||
if (!plugin || !plugin->info) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!min) {
|
||||
min = plugin? plugin->minstrlen: 4;
|
||||
}
|
||||
/* Some plugins return zero, fix it up */
|
||||
if (!min) {
|
||||
min = 4;
|
||||
}
|
||||
if (min < 0) {
|
||||
return;
|
||||
}
|
||||
if (!to || to > bf->buf->length) {
|
||||
to = r_buf_size (bf->buf);
|
||||
}
|
||||
if (!to) {
|
||||
return;
|
||||
}
|
||||
if (raw != 2) {
|
||||
ut64 size = to - from;
|
||||
// in case of dump ignore here
|
||||
if (bf->rbin->maxstrbuf && size && size > bf->rbin->maxstrbuf) {
|
||||
if (bf->rbin->verbose) {
|
||||
eprintf ("WARNING: bin_strings buffer is too big (0x%08" PFMT64x "). Use -zzz or set bin.maxstrbuf (RABIN2_MAXSTRBUF) in r2 (rabin2)\n",
|
||||
size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (string_scan_range (list, bf, min, from, to, -1) < 0) {
|
||||
return;
|
||||
}
|
||||
if (bf->o) {
|
||||
r_list_foreach (list, it, ptr) {
|
||||
RBinSection *s = r_bin_get_section_at (bf->o, ptr->paddr, false);
|
||||
if (s) {
|
||||
ptr->vaddr = s->vaddr + (ptr->paddr - s->paddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
R_IPI RList *r_bin_file_get_strings(RBinFile *a, int min, int dump, int raw) {
|
||||
r_return_val_if_fail (a, NULL);
|
||||
RListIter *iter;
|
||||
|
@ -56,9 +56,7 @@ static ut64 binobj_a2b(RBinObject *o, ut64 addr) {
|
||||
}
|
||||
|
||||
// TODO: move these two function do a different file
|
||||
R_API RBinXtrData *r_bin_xtrdata_new(RBuffer *buf, ut64 offset, ut64 size,
|
||||
ut32 file_count,
|
||||
RBinXtrMetadata *metadata) {
|
||||
R_API RBinXtrData *r_bin_xtrdata_new(RBuffer *buf, ut64 offset, ut64 size, ut32 file_count, RBinXtrMetadata *metadata) {
|
||||
RBinXtrData *data = R_NEW0 (RBinXtrData);
|
||||
if (!data) {
|
||||
return NULL;
|
||||
@ -69,15 +67,8 @@ R_API RBinXtrData *r_bin_xtrdata_new(RBuffer *buf, ut64 offset, ut64 size,
|
||||
data->metadata = metadata;
|
||||
data->loaded = 0;
|
||||
// TODO: USE RBuffer *buf inside RBinXtrData*
|
||||
data->buffer = malloc (size + 1);
|
||||
// data->laddr = 0; /// XXX
|
||||
if (!data->buffer) {
|
||||
free (data);
|
||||
return NULL;
|
||||
}
|
||||
// XXX unnecessary memcpy, this is slow
|
||||
memcpy (data->buffer, r_buf_buffer (buf), size);
|
||||
data->buffer[size] = 0;
|
||||
data->buf = r_buf_ref (buf);
|
||||
// TODO. subbuffer?
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -102,7 +93,7 @@ R_API void r_bin_xtrdata_free(void /*RBinXtrData*/ *data_) {
|
||||
free (data->metadata);
|
||||
}
|
||||
free (data->file);
|
||||
free (data->buffer);
|
||||
r_buf_free (data->buf);
|
||||
free (data);
|
||||
}
|
||||
|
||||
|
@ -330,7 +330,7 @@ typedef struct r_bin_xtr_metadata_t {
|
||||
typedef int (*FREE_XTR)(void *xtr_obj);
|
||||
typedef struct r_bin_xtr_extract_t {
|
||||
char *file;
|
||||
ut8 *buffer;
|
||||
RBuffer *buf;
|
||||
ut64 size;
|
||||
ut64 offset;
|
||||
ut64 baddr;
|
||||
|
@ -44,6 +44,7 @@ R_API RBuffer *r_buf_new_with_bytes(const ut8* bytes, ut64 len);
|
||||
R_API RBuffer *r_buf_new_with_string (const char *msg);
|
||||
R_API RBuffer *r_buf_new_with_pointers(const ut8 *bytes, ut64 len);
|
||||
R_API RBuffer *r_buf_new_with_buf(RBuffer *b);
|
||||
R_API RBuffer *r_buf_new_with_bufref(RBuffer *b);
|
||||
R_API RBuffer *r_buf_new_file(const char *file, bool newFile);
|
||||
R_API RBuffer *r_buf_new_slurp(const char *file);
|
||||
R_API RBuffer *r_buf_new_empty (ut64 len);
|
||||
|
434
libr/util/buf.c
434
libr/util/buf.c
@ -106,6 +106,200 @@ static bool sparse_limits(RList *l, ut64 *min, ut64 *max) {
|
||||
return set;
|
||||
}
|
||||
|
||||
static ut64 remainingBytes(ut64 limit, ut64 length, ut64 offset) {
|
||||
if (offset >= length ) {
|
||||
return 0;
|
||||
}
|
||||
return R_MIN (limit, length - offset);
|
||||
}
|
||||
// ret copied length if successful, -1 if failed
|
||||
static int r_buf_cpy(RBuffer *b, ut64 addr, ut8 *dst, const ut8 *src, int len, int write) {
|
||||
r_return_val_if_fail (b && !b->empty, 0);
|
||||
|
||||
ut64 start = addr - b->base + b->offset;
|
||||
ut64 effective_size = r_buf_size (b);
|
||||
int real_len = len;
|
||||
if (start - b->offset + len > effective_size) {
|
||||
real_len = effective_size - start + b->offset;
|
||||
}
|
||||
if (real_len < 1) {
|
||||
return 0;
|
||||
}
|
||||
if (b->iob) {
|
||||
RIOBind *iob = b->iob;
|
||||
if (b->fd != -1) {
|
||||
return write
|
||||
? iob->fd_write_at (iob->io, b->fd, start, src, real_len)
|
||||
: iob->fd_read_at (iob->io, b->fd, start, dst, real_len);
|
||||
}
|
||||
return write
|
||||
? iob->write_at (iob->io, start, src, real_len)
|
||||
: iob->read_at (iob->io, start, dst, real_len);
|
||||
}
|
||||
if (b->fd != -1) {
|
||||
if (r_sandbox_lseek (b->fd, start, SEEK_SET) == -1) {
|
||||
// seek failed - print error here?
|
||||
// return 0;
|
||||
}
|
||||
if (write) {
|
||||
return r_sandbox_write (b->fd, src, real_len);
|
||||
}
|
||||
memset (dst, 0, real_len);
|
||||
return r_sandbox_read (b->fd, dst, real_len);
|
||||
}
|
||||
if (b->sparse) {
|
||||
if (write) {
|
||||
// create new with src + len
|
||||
if (sparse_write (b->sparse, start, src, real_len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
// read from sparse and write into dst
|
||||
memset (dst, b->Oxff, len);
|
||||
(void)sparse_read (b->sparse, start, dst, real_len);
|
||||
len = R_MIN (real_len , r_buf_size (b) - addr);
|
||||
}
|
||||
return real_len;
|
||||
}
|
||||
addr = (addr == R_BUF_CUR) ? b->cur : start;
|
||||
if (len < 1 || !dst || addr - b->offset > effective_size) {
|
||||
return -1;
|
||||
}
|
||||
if (write) {
|
||||
dst += addr;
|
||||
} else {
|
||||
src += addr;
|
||||
}
|
||||
memmove (dst, src, real_len);
|
||||
b->cur = addr + real_len;
|
||||
return real_len;
|
||||
}
|
||||
|
||||
static int r_buf_fcpy_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int n, int write) {
|
||||
ut64 len, check_len;
|
||||
int i, j, k, tsize, m = 1;
|
||||
bool bigendian = true;
|
||||
r_return_val_if_fail (b && !b->empty, 0);
|
||||
|
||||
if ((b->iob || b->fd != -1) && write) {
|
||||
eprintf ("r_buf_fcpy_at write not supported yet for r_buf_new_file\n");
|
||||
return 0;
|
||||
}
|
||||
ut64 vaddr;
|
||||
if (addr == R_BUF_CUR) {
|
||||
vaddr = addr = b->cur;
|
||||
} else {
|
||||
vaddr = addr;
|
||||
addr = addr - b->base + b->offset;
|
||||
}
|
||||
ut64 effective_size = r_buf_size (b);
|
||||
if (addr == UT64_MAX || addr > effective_size) {
|
||||
return -1;
|
||||
}
|
||||
tsize = 2;
|
||||
for (i = len = 0; i < n; i++) {
|
||||
for (j = 0; fmt[j]; j++) {
|
||||
switch (fmt[j]) {
|
||||
#ifdef _MSC_VER
|
||||
case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9':
|
||||
#else
|
||||
case '0'...'9':
|
||||
#endif
|
||||
if (m == 1) {
|
||||
m = r_num_get (NULL, &fmt[j]);
|
||||
}
|
||||
continue;
|
||||
case 's': tsize = 2; bigendian = false; break;
|
||||
case 'S': tsize = 2; bigendian = true; break;
|
||||
case 'i': tsize = 4; bigendian = false; break;
|
||||
case 'I': tsize = 4; bigendian = true; break;
|
||||
case 'l': tsize = 8; bigendian = false; break;
|
||||
case 'L': tsize = 8; bigendian = true; break;
|
||||
case 'c': tsize = 1; bigendian = false; break;
|
||||
default: return -1;
|
||||
}
|
||||
|
||||
/* Avoid read/write out of bound.
|
||||
tsize and m are not user controled, then don't
|
||||
need to check possible overflow.
|
||||
*/
|
||||
if (!UT64_ADD (&check_len, len, tsize*m)) {
|
||||
return -1;
|
||||
}
|
||||
if (!UT64_ADD (&check_len, check_len, addr)) {
|
||||
return -1;
|
||||
}
|
||||
if (check_len > effective_size) {
|
||||
return check_len;
|
||||
}
|
||||
|
||||
for (k = 0; k < m; k++) {
|
||||
ut8 _dest1[sizeof (ut64)] = {0};
|
||||
ut8 _dest2[sizeof (ut64)] = {0};
|
||||
int left1, left2;
|
||||
ut64 addr1 = len + (k * tsize);
|
||||
ut64 addr2 = vaddr + addr1;
|
||||
ut8 *src1=NULL, *src2=NULL;
|
||||
if (b->fd == -1) {
|
||||
src1 = r_buf_get_at (b, addr1, &left1);
|
||||
src2 = r_buf_get_at (b, addr2, &left2);
|
||||
}
|
||||
if (!src1 || !src2) {
|
||||
left1 = r_buf_read_at (b, addr1, _dest1, sizeof (_dest1));
|
||||
left2 = r_buf_read_at (b, addr2, _dest2, sizeof (_dest2));
|
||||
src1 = _dest1;
|
||||
src2 = _dest2;
|
||||
}
|
||||
void* dest1 = buf + addr + addr1; // shouldn't this be an address in b ?
|
||||
void* dest2 = buf + addr1;
|
||||
ut8* dest1_8 = (ut8*)dest1;
|
||||
ut16* dest1_16 = (ut16*)dest1;
|
||||
ut32* dest1_32 = (ut32*)dest1;
|
||||
ut64* dest1_64 = (ut64*)dest1;
|
||||
ut8* dest2_8 = (ut8*)dest2;
|
||||
ut16* dest2_16 = (ut16*)dest2;
|
||||
ut32* dest2_32 = (ut32*)dest2;
|
||||
ut64* dest2_64 = (ut64*)dest2;
|
||||
if (write) {
|
||||
switch (tsize) {
|
||||
case 1:
|
||||
*dest1_8 = r_read_ble8 (src1);
|
||||
break;
|
||||
case 2:
|
||||
*dest1_16 = r_read_ble16 (src1, bigendian);
|
||||
break;
|
||||
case 4:
|
||||
*dest1_32 = r_read_ble32 (src1, bigendian);
|
||||
break;
|
||||
case 8:
|
||||
*dest1_64 = r_read_ble64 (src1, bigendian);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (tsize) {
|
||||
case 1:
|
||||
*dest2_8 = r_read_ble8 (src2);
|
||||
break;
|
||||
case 2:
|
||||
*dest2_16 = r_read_ble16 (src2, bigendian);
|
||||
break;
|
||||
case 4:
|
||||
*dest2_32 = r_read_ble32 (src2, bigendian);
|
||||
break;
|
||||
case 8:
|
||||
*dest2_64 = r_read_ble64 (src2, bigendian);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
len += tsize * m;
|
||||
m = 1;
|
||||
}
|
||||
}
|
||||
b->cur = vaddr + len;
|
||||
return len;
|
||||
}
|
||||
|
||||
R_API RBuffer *r_buf_new_with_io(void *iob, int fd) {
|
||||
RBuffer *b = r_buf_new ();
|
||||
b->iob = iob;
|
||||
@ -171,9 +365,7 @@ R_API RBuffer *r_buf_new_sparse(ut8 Oxff) {
|
||||
}
|
||||
|
||||
R_API RBuffer *r_buf_new_slice(RBuffer *b, ut64 offset, ut64 size) {
|
||||
if (!b) {
|
||||
return NULL;
|
||||
}
|
||||
r_return_val_if_fail (b, NULL);
|
||||
if (b->sparse) {
|
||||
eprintf ("r_buf_new_slice not supported yet for sparse buffers\n");
|
||||
return NULL;
|
||||
@ -208,13 +400,6 @@ R_API const ut8 *r_buf_buffer (RBuffer *b) {
|
||||
return (b && !b->sparse)? b->buf: NULL;
|
||||
}
|
||||
|
||||
static ut64 remainingBytes(ut64 limit, ut64 length, ut64 offset) {
|
||||
if (offset >= length ) {
|
||||
return 0;
|
||||
}
|
||||
return R_MIN (limit, length - offset);
|
||||
}
|
||||
|
||||
R_API ut64 r_buf_size (RBuffer *b) {
|
||||
if (!b) {
|
||||
return 0LL;
|
||||
@ -515,196 +700,6 @@ R_API bool r_buf_append_buf(RBuffer *b, RBuffer *a) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ret copied length if successful, -1 if failed
|
||||
static int r_buf_cpy(RBuffer *b, ut64 addr, ut8 *dst, const ut8 *src, int len, int write) {
|
||||
if (!b || b->empty) {
|
||||
return 0;
|
||||
}
|
||||
ut64 start = addr - b->base + b->offset;
|
||||
ut64 effective_size = r_buf_size (b);
|
||||
int real_len = len;
|
||||
if (start - b->offset + len > effective_size) {
|
||||
real_len = effective_size - start + b->offset;
|
||||
}
|
||||
if (real_len < 1) {
|
||||
return 0;
|
||||
}
|
||||
if (b->iob) {
|
||||
RIOBind *iob = b->iob;
|
||||
if (b->fd != -1) {
|
||||
return write
|
||||
? iob->fd_write_at (iob->io, b->fd, start, src, real_len)
|
||||
: iob->fd_read_at (iob->io, b->fd, start, dst, real_len);
|
||||
}
|
||||
return write
|
||||
? iob->write_at (iob->io, start, src, real_len)
|
||||
: iob->read_at (iob->io, start, dst, real_len);
|
||||
}
|
||||
if (b->fd != -1) {
|
||||
if (r_sandbox_lseek (b->fd, start, SEEK_SET) == -1) {
|
||||
// seek failed - print error here?
|
||||
// return 0;
|
||||
}
|
||||
if (write) {
|
||||
return r_sandbox_write (b->fd, src, real_len);
|
||||
}
|
||||
memset (dst, 0, real_len);
|
||||
return r_sandbox_read (b->fd, dst, real_len);
|
||||
}
|
||||
if (b->sparse) {
|
||||
if (write) {
|
||||
// create new with src + len
|
||||
if (sparse_write (b->sparse, start, src, real_len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
// read from sparse and write into dst
|
||||
memset (dst, b->Oxff, len);
|
||||
(void)sparse_read (b->sparse, start, dst, real_len);
|
||||
len = R_MIN (real_len , r_buf_size (b) - addr);
|
||||
}
|
||||
return real_len;
|
||||
}
|
||||
addr = (addr == R_BUF_CUR) ? b->cur : start;
|
||||
if (len < 1 || !dst || addr - b->offset > effective_size) {
|
||||
return -1;
|
||||
}
|
||||
if (write) {
|
||||
dst += addr;
|
||||
} else {
|
||||
src += addr;
|
||||
}
|
||||
memmove (dst, src, real_len);
|
||||
b->cur = addr + real_len;
|
||||
return real_len;
|
||||
}
|
||||
|
||||
static int r_buf_fcpy_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int n, int write) {
|
||||
ut64 len, check_len;
|
||||
int i, j, k, tsize, m = 1;
|
||||
bool bigendian = true;
|
||||
if (!b || b->empty) {
|
||||
return 0;
|
||||
}
|
||||
if ((b->iob || b->fd != -1) && write) {
|
||||
eprintf ("r_buf_fcpy_at write not supported yet for r_buf_new_file\n");
|
||||
return 0;
|
||||
}
|
||||
ut64 vaddr;
|
||||
if (addr == R_BUF_CUR) {
|
||||
vaddr = addr = b->cur;
|
||||
} else {
|
||||
vaddr = addr;
|
||||
addr = addr - b->base + b->offset;
|
||||
}
|
||||
ut64 effective_size = r_buf_size (b);
|
||||
if (addr == UT64_MAX || addr > effective_size) {
|
||||
return -1;
|
||||
}
|
||||
tsize = 2;
|
||||
for (i = len = 0; i < n; i++) {
|
||||
for (j = 0; fmt[j]; j++) {
|
||||
switch (fmt[j]) {
|
||||
#ifdef _MSC_VER
|
||||
case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9':
|
||||
#else
|
||||
case '0'...'9':
|
||||
#endif
|
||||
if (m == 1) {
|
||||
m = r_num_get (NULL, &fmt[j]);
|
||||
}
|
||||
continue;
|
||||
case 's': tsize = 2; bigendian = false; break;
|
||||
case 'S': tsize = 2; bigendian = true; break;
|
||||
case 'i': tsize = 4; bigendian = false; break;
|
||||
case 'I': tsize = 4; bigendian = true; break;
|
||||
case 'l': tsize = 8; bigendian = false; break;
|
||||
case 'L': tsize = 8; bigendian = true; break;
|
||||
case 'c': tsize = 1; bigendian = false; break;
|
||||
default: return -1;
|
||||
}
|
||||
|
||||
/* Avoid read/write out of bound.
|
||||
tsize and m are not user controled, then don't
|
||||
need to check possible overflow.
|
||||
*/
|
||||
if (!UT64_ADD (&check_len, len, tsize*m)) {
|
||||
return -1;
|
||||
}
|
||||
if (!UT64_ADD (&check_len, check_len, addr)) {
|
||||
return -1;
|
||||
}
|
||||
if (check_len > effective_size) {
|
||||
return check_len;
|
||||
}
|
||||
|
||||
for (k = 0; k < m; k++) {
|
||||
ut8 _dest1[sizeof (ut64)] = {0};
|
||||
ut8 _dest2[sizeof (ut64)] = {0};
|
||||
int left1, left2;
|
||||
ut64 addr1 = len + (k * tsize);
|
||||
ut64 addr2 = vaddr + addr1;
|
||||
ut8 *src1=NULL, *src2=NULL;
|
||||
if (b->fd == -1) {
|
||||
src1 = r_buf_get_at (b, addr1, &left1);
|
||||
src2 = r_buf_get_at (b, addr2, &left2);
|
||||
}
|
||||
if (!src1 || !src2) {
|
||||
left1 = r_buf_read_at (b, addr1, _dest1, sizeof (_dest1));
|
||||
left2 = r_buf_read_at (b, addr2, _dest2, sizeof (_dest2));
|
||||
src1 = _dest1;
|
||||
src2 = _dest2;
|
||||
}
|
||||
void* dest1 = buf + addr + addr1; // shouldn't this be an address in b ?
|
||||
void* dest2 = buf + addr1;
|
||||
ut8* dest1_8 = (ut8*)dest1;
|
||||
ut16* dest1_16 = (ut16*)dest1;
|
||||
ut32* dest1_32 = (ut32*)dest1;
|
||||
ut64* dest1_64 = (ut64*)dest1;
|
||||
ut8* dest2_8 = (ut8*)dest2;
|
||||
ut16* dest2_16 = (ut16*)dest2;
|
||||
ut32* dest2_32 = (ut32*)dest2;
|
||||
ut64* dest2_64 = (ut64*)dest2;
|
||||
if (write) {
|
||||
switch (tsize) {
|
||||
case 1:
|
||||
*dest1_8 = r_read_ble8 (src1);
|
||||
break;
|
||||
case 2:
|
||||
*dest1_16 = r_read_ble16 (src1, bigendian);
|
||||
break;
|
||||
case 4:
|
||||
*dest1_32 = r_read_ble32 (src1, bigendian);
|
||||
break;
|
||||
case 8:
|
||||
*dest1_64 = r_read_ble64 (src1, bigendian);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (tsize) {
|
||||
case 1:
|
||||
*dest2_8 = r_read_ble8 (src2);
|
||||
break;
|
||||
case 2:
|
||||
*dest2_16 = r_read_ble16 (src2, bigendian);
|
||||
break;
|
||||
case 4:
|
||||
*dest2_32 = r_read_ble32 (src2, bigendian);
|
||||
break;
|
||||
case 8:
|
||||
*dest2_64 = r_read_ble64 (src2, bigendian);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
len += tsize * m;
|
||||
m = 1;
|
||||
}
|
||||
}
|
||||
b->cur = vaddr + len;
|
||||
return len;
|
||||
}
|
||||
|
||||
R_API ut8 *r_buf_get_at(RBuffer *b, ut64 addr, int *left) {
|
||||
if (b->empty) {
|
||||
return NULL;
|
||||
@ -843,25 +838,6 @@ R_API int r_buf_fwrite_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int
|
||||
return r_buf_fcpy_at (b, addr, buf, fmt, n, true);
|
||||
}
|
||||
|
||||
R_API void r_buf_deinit(RBuffer *b) {
|
||||
if (!b) {
|
||||
return;
|
||||
}
|
||||
if (b->fd != -1) {
|
||||
r_sandbox_close (b->fd);
|
||||
b->fd = -1;
|
||||
return;
|
||||
}
|
||||
if (b->sparse) {
|
||||
r_list_free (b->sparse);
|
||||
b->sparse = NULL;
|
||||
}
|
||||
if (b->mmap) {
|
||||
r_file_mmap_free (b->mmap);
|
||||
b->mmap = NULL;
|
||||
} else R_FREE (b->buf);
|
||||
}
|
||||
|
||||
R_API bool r_buf_fini(RBuffer *b) {
|
||||
if (!b) {
|
||||
return false;
|
||||
@ -878,7 +854,21 @@ R_API bool r_buf_fini(RBuffer *b) {
|
||||
return false;
|
||||
}
|
||||
if (!b->ro) {
|
||||
r_buf_deinit (b);
|
||||
if (b->fd != -1) {
|
||||
r_sandbox_close (b->fd);
|
||||
b->fd = -1;
|
||||
return false;
|
||||
}
|
||||
if (b->sparse) {
|
||||
r_list_free (b->sparse);
|
||||
b->sparse = NULL;
|
||||
}
|
||||
if (b->mmap) {
|
||||
r_file_mmap_free (b->mmap);
|
||||
b->mmap = NULL;
|
||||
} else {
|
||||
R_FREE (b->buf);
|
||||
}
|
||||
}
|
||||
// true -> can bee free()d
|
||||
return true;
|
||||
@ -895,10 +885,8 @@ R_API int r_buf_append_string (RBuffer *b, const char *str) {
|
||||
}
|
||||
|
||||
R_API char *r_buf_free_to_string(RBuffer *b) {
|
||||
r_return_val_if_fail (b, NULL);
|
||||
char *p;
|
||||
if (!b) {
|
||||
return NULL;
|
||||
}
|
||||
if (b->mmap) {
|
||||
p = r_buf_to_string (b);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user