mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-11 23:16:05 +00:00
Some fix in the ELF parser
New functions used to prevent integer overflow when add, sub or mul Fix an out of bound in r_buf_fcpy_at
This commit is contained in:
parent
c5d65fbd42
commit
eb6b86dd4b
@ -19,9 +19,9 @@ static inline int __strnlen(const char *str, int len) {
|
||||
}
|
||||
|
||||
static int Elf_(r_bin_elf_init_ehdr)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
ut8 e_ident[16];
|
||||
ut8 e_ident[EI_NIDENT];
|
||||
int len;
|
||||
if (r_buf_read_at (bin->b, 0, e_ident, 16) == -1) {
|
||||
if (r_buf_read_at (bin->b, 0, e_ident, EI_NIDENT) == -1) {
|
||||
eprintf ("Warning: read (magic)\n");
|
||||
return R_FALSE;
|
||||
}
|
||||
@ -44,12 +44,20 @@ static int Elf_(r_bin_elf_init_ehdr)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
}
|
||||
|
||||
static int Elf_(r_bin_elf_init_phdr)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
int phdr_size, len;
|
||||
ut32 phdr_size;
|
||||
int len;
|
||||
|
||||
if (bin->ehdr.e_phnum == 0)
|
||||
return R_FALSE;
|
||||
if (bin->phdr) return R_TRUE;
|
||||
phdr_size = bin->ehdr.e_phnum * sizeof (Elf_(Phdr));
|
||||
if ((bin->phdr = (Elf_(Phdr) *)malloc (phdr_size)) == NULL) {
|
||||
|
||||
if(!UT32_MUL(&phdr_size, bin->ehdr.e_phnum, sizeof(Elf_(Phdr))))
|
||||
return R_FALSE;
|
||||
|
||||
if(!phdr_size)
|
||||
return R_FALSE;
|
||||
|
||||
if ((bin->phdr = malloc (phdr_size)) == NULL) {
|
||||
perror ("malloc (phdr)");
|
||||
return R_FALSE;
|
||||
}
|
||||
@ -70,10 +78,18 @@ static int Elf_(r_bin_elf_init_phdr)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
}
|
||||
|
||||
static int Elf_(r_bin_elf_init_shdr)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
int len, shdr_size;
|
||||
ut32 shdr_size;
|
||||
int len;
|
||||
|
||||
if (bin->shdr) return R_TRUE;
|
||||
shdr_size = bin->ehdr.e_shnum * sizeof (Elf_(Shdr));
|
||||
if ((bin->shdr = (Elf_(Shdr) *)malloc (shdr_size)) == NULL) {
|
||||
|
||||
if(!UT32_MUL(&shdr_size, bin->ehdr.e_shnum, sizeof (Elf_(Shdr))))
|
||||
return R_FALSE;
|
||||
|
||||
if(!shdr_size)
|
||||
return R_FALSE;
|
||||
|
||||
if ((bin->shdr = malloc (shdr_size)) == NULL) {
|
||||
perror ("malloc (shdr)");
|
||||
return R_FALSE;
|
||||
}
|
||||
@ -93,33 +109,33 @@ static int Elf_(r_bin_elf_init_shdr)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
}
|
||||
|
||||
static int Elf_(r_bin_elf_init_strtab)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
int sz;
|
||||
if (bin->strtab || !bin->shdr) return R_FALSE;
|
||||
if (bin->ehdr.e_shstrndx != SHN_UNDEF &&
|
||||
(bin->ehdr.e_shstrndx >= bin->ehdr.e_shnum ||
|
||||
(bin->ehdr.e_shstrndx >= SHN_LORESERVE && bin->ehdr.e_shstrndx <= SHN_HIRESERVE)))
|
||||
return R_FALSE;
|
||||
|
||||
/* sh_size must be lower than UT32_MAX and not equal to zero, to avoid bugs
|
||||
on malloc() */
|
||||
if(bin->shdr[bin->ehdr.e_shstrndx].sh_size > UT32_MAX)
|
||||
return R_FALSE;
|
||||
if(!bin->shdr[bin->ehdr.e_shstrndx].sh_size)
|
||||
return R_FALSE;
|
||||
|
||||
bin->shstrtab_section =
|
||||
bin->strtab_section = &bin->shdr[bin->ehdr.e_shstrndx];
|
||||
if (bin->strtab_section == NULL)
|
||||
return R_FALSE;
|
||||
if (bin->strtab_section->sh_size > (0xffff - sizeof (struct r_bin_elf_section_t)))
|
||||
bin->strtab_section->sh_size = 0xffff - sizeof (struct r_bin_elf_section_t);
|
||||
|
||||
bin->shstrtab_size =
|
||||
bin->strtab_size = bin->strtab_section->sh_size;
|
||||
sz = sizeof (struct r_bin_elf_section_t) + bin->strtab_section->sh_size;
|
||||
if ((bin->strtab = (char *)malloc (sz)) == NULL) {
|
||||
|
||||
if ((bin->strtab = malloc (bin->strtab_size)) == NULL) {
|
||||
perror ("malloc");
|
||||
bin->shstrtab = NULL;
|
||||
return R_FALSE;
|
||||
}
|
||||
memset (bin->strtab, 0, sz);
|
||||
memset (bin->strtab, 0, bin->strtab_size);
|
||||
bin->shstrtab = bin->strtab;
|
||||
//bin->strtab_section->sh_offset = 0;
|
||||
if (!bin->strtab_section->sh_offset) {
|
||||
bin->strtab = NULL;
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
if (r_buf_read_at (bin->b, bin->strtab_section->sh_offset, (ut8*)bin->strtab,
|
||||
bin->strtab_section->sh_size) == -1) {
|
||||
eprintf ("Warning: read (strtab) at 0x%"PFMT64x"\n",
|
||||
@ -131,73 +147,17 @@ static int Elf_(r_bin_elf_init_strtab)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static ut64 Elf_(r_bin_elf_get_section_size)(struct Elf_(r_bin_elf_obj_t) *bin, const char *section_name) {
|
||||
int i;
|
||||
if (!bin->shdr || !bin->strtab)
|
||||
return -1;
|
||||
for (i = 0; i < bin->ehdr.e_shnum; i++) {
|
||||
if (bin->shdr[i].sh_name > bin->shstrtab_section->sh_size)
|
||||
continue;
|
||||
if (!strcmp (&bin->shstrtab[bin->shdr[i].sh_name], section_name))
|
||||
return (ut64)bin->shdr[i].sh_size;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int Elf_(r_bin_elf_init_strtab)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
ut64 size;
|
||||
if (!bin->shstrtab)
|
||||
return R_FALSE;
|
||||
bin->shstrtab_section = &bin->shdr[bin->ehdr.e_shstrndx];
|
||||
bin->shstrtab_size = size = 4096; //bin->shstrtab_section->sh_size;
|
||||
|
||||
if ((bin->shstrtab = (char *)malloc (size)) == NULL) {
|
||||
perror ("malloc");
|
||||
return R_FALSE;
|
||||
}
|
||||
//eprintf ("BUFBUFBUF %p\n",
|
||||
eprintf ("%p off=%x buf=%p sz=%llx\n",
|
||||
bin->b, bin->shstrtab_section->sh_offset, (ut8*)bin->shstrtab, size);
|
||||
if (r_buf_read_at (bin->b, (ut64)bin->shstrtab_section->sh_offset, (ut8*)bin->shstrtab, size) == -1) {
|
||||
eprintf ("Warning: read (strtab)\n");
|
||||
R_FREE (bin->strtab);
|
||||
return R_FALSE;
|
||||
}
|
||||
write (1, "\n\n", 2);
|
||||
write (1, bin->shstrtab, size);
|
||||
write (1, "\n\n", 2);
|
||||
|
||||
size = Elf_(r_bin_elf_get_section_size)(bin, ".strtab");
|
||||
if (size != UT64_MAX) {
|
||||
ut64 off = Elf_(r_bin_elf_get_section_offset)(bin, ".strtab");
|
||||
bin->strtab_size = size;
|
||||
free (bin->strtab);
|
||||
if ((bin->strtab = (char *)malloc (size+1)) == NULL) {
|
||||
perror ("malloc");
|
||||
return R_FALSE;
|
||||
}
|
||||
if (r_buf_read_at (bin->b, off, (ut8*)bin->strtab, size) == -1) {
|
||||
eprintf ("Warning: read (strtab)\n");
|
||||
R_FREE (bin->strtab);
|
||||
return R_FALSE;
|
||||
}
|
||||
}
|
||||
return R_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int Elf_(r_bin_elf_init)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
bin->phdr = NULL;
|
||||
bin->shdr = NULL;
|
||||
bin->strtab = NULL;
|
||||
bin->strtab_size = 0;
|
||||
bin->strtab_section = NULL;
|
||||
if (!Elf_(r_bin_elf_init_ehdr) (bin)) {
|
||||
//eprintf ("Warning: File is not ELF\n");
|
||||
|
||||
/* bin is not an ELF */
|
||||
if (!Elf_(r_bin_elf_init_ehdr) (bin))
|
||||
return R_FALSE;
|
||||
}
|
||||
// Elf_(r_bin_elf_init_phdr) (bin);
|
||||
|
||||
if (!Elf_(r_bin_elf_init_phdr) (bin))
|
||||
eprintf ("Warning: Cannot initialize program headers\n");
|
||||
if (!Elf_(r_bin_elf_init_shdr) (bin))
|
||||
@ -216,37 +176,47 @@ static int Elf_(r_bin_elf_init)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
static ut64 Elf_(r_bin_elf_get_section_offset)(struct Elf_(r_bin_elf_obj_t) *bin, const char *section_name) {
|
||||
static Elf_(Shdr)* Elf_(r_bin_elf_get_section_by_name)(struct Elf_(r_bin_elf_obj_t) *bin, const char *section_name) {
|
||||
int i;
|
||||
ut32 cur_strtab_len;
|
||||
|
||||
if (!bin->shdr || !bin->strtab)
|
||||
return -1;
|
||||
return NULL;
|
||||
for (i = 0; i < bin->ehdr.e_shnum; i++) {
|
||||
if (bin->shdr[i].sh_name > bin->shstrtab_section->sh_size)
|
||||
if(!UT32_SUB(&cur_strtab_len, bin->shstrtab_section->sh_size, bin->shdr[i].sh_name))
|
||||
continue;
|
||||
if (!strcmp (&bin->shstrtab[bin->shdr[i].sh_name], section_name))
|
||||
return (ut64)bin->shdr[i].sh_offset;
|
||||
if (!strncmp (&bin->shstrtab[bin->shdr[i].sh_name], section_name, cur_strtab_len))
|
||||
return &bin->shdr[i];
|
||||
}
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ut64 Elf_(r_bin_elf_get_section_offset)(struct Elf_(r_bin_elf_obj_t) *bin, const char *section_name) {
|
||||
Elf_(Shdr)* shdr;
|
||||
|
||||
shdr = Elf_(r_bin_elf_get_section_by_name)(bin, section_name);
|
||||
|
||||
if (!shdr)
|
||||
return -1;
|
||||
return (ut64)shdr->sh_offset;
|
||||
}
|
||||
|
||||
ut64 Elf_(r_bin_elf_get_section_addr)(struct Elf_(r_bin_elf_obj_t) *bin, const char *section_name) {
|
||||
int i;
|
||||
if (!bin->shdr || !bin->strtab)
|
||||
Elf_(Shdr)* shdr;
|
||||
|
||||
shdr = Elf_(r_bin_elf_get_section_by_name)(bin, section_name);
|
||||
|
||||
if (!shdr)
|
||||
return -1;
|
||||
for (i = 0; i < bin->ehdr.e_shnum; i++) {
|
||||
if (bin->shdr[i].sh_name > bin->shstrtab_section->sh_size)
|
||||
continue;
|
||||
if (!strcmp (&bin->strtab[bin->shdr[i].sh_name], section_name))
|
||||
return (ut64)bin->shdr[i].sh_addr;
|
||||
}
|
||||
return -1;
|
||||
return (ut64)shdr->sh_addr;
|
||||
}
|
||||
|
||||
static ut64 Elf_(get_import_addr)(struct Elf_(r_bin_elf_obj_t) *bin, int sym) {
|
||||
Elf_(Rel) *rel = NULL;
|
||||
Elf_(Rel) *rel;
|
||||
Elf_(Shdr) *rel_shdr;
|
||||
Elf_(Addr) plt_sym_addr;
|
||||
ut64 got_addr, got_offset;
|
||||
int i, j, k, tsize, len;
|
||||
int j, k, tsize, len;
|
||||
|
||||
if (!bin->shdr || !bin->strtab)
|
||||
return -1;
|
||||
@ -256,50 +226,48 @@ static ut64 Elf_(get_import_addr)(struct Elf_(r_bin_elf_obj_t) *bin, int sym) {
|
||||
if ((got_addr = Elf_(r_bin_elf_get_section_addr) (bin, ".got")) == -1 &&
|
||||
(got_addr = Elf_(r_bin_elf_get_section_addr) (bin, ".got.plt")) == -1)
|
||||
return -1;
|
||||
for (i = 0; i < bin->ehdr.e_shnum; i++) {
|
||||
if (bin->shdr[i].sh_name > bin->shstrtab_section->sh_size)
|
||||
continue;
|
||||
if (!strcmp (&bin->strtab[bin->shdr[i].sh_name], ".rel.plt"))
|
||||
tsize = sizeof (Elf_(Rel));
|
||||
else if (!strcmp (&bin->strtab[bin->shdr[i].sh_name], ".rela.plt"))
|
||||
tsize = sizeof (Elf_(Rela));
|
||||
else continue;
|
||||
|
||||
free (rel);
|
||||
if ((rel = (Elf_(Rel) *)malloc ((int)(bin->shdr[i].sh_size / tsize) * sizeof (Elf_(Rel)))) == NULL) {
|
||||
perror ("malloc (rel)");
|
||||
return -1;
|
||||
}
|
||||
for (j = k = 0; j < bin->shdr[i].sh_size; j += tsize, k++) {
|
||||
len = r_buf_fread_at (bin->b, bin->shdr[i].sh_offset + j, (ut8*)&rel[k],
|
||||
#if R_BIN_ELF64
|
||||
bin->endian?"2L":"2l",
|
||||
#else
|
||||
bin->endian?"2I":"2i",
|
||||
#endif
|
||||
1);
|
||||
if (len == -1) {
|
||||
eprintf ("Warning: read (rel)\n");
|
||||
free (rel);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
for (j = k = 0; j < bin->shdr[i].sh_size; j += tsize, k++) {
|
||||
if (ELF_R_SYM (rel[k].r_info) == sym) {
|
||||
if (r_buf_read_at (bin->b, rel[k].r_offset-got_addr+got_offset,
|
||||
(ut8*)&plt_sym_addr, sizeof (Elf_(Addr))) == -1) {
|
||||
eprintf ("Warning: read (got)\n");
|
||||
free (rel);
|
||||
return UT64_MAX;
|
||||
}
|
||||
free (rel);
|
||||
return (ut64)(plt_sym_addr - 6);
|
||||
}
|
||||
}
|
||||
break;
|
||||
if((rel_shdr = Elf_(r_bin_elf_get_section_by_name)(bin, ".rel.plt")) != NULL) {
|
||||
tsize = sizeof (Elf_(Rel));
|
||||
} else if((rel_shdr = Elf_(r_bin_elf_get_section_by_name)(bin, ".rela.plt")) != NULL) {
|
||||
tsize = sizeof (Elf_(Rela));
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
free (rel);
|
||||
return UT64_MAX;
|
||||
|
||||
if ((rel = malloc ((rel_shdr->sh_size / tsize) * sizeof (Elf_(Rel)))) == NULL) {
|
||||
perror ("malloc (rel)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
plt_sym_addr = -1;
|
||||
|
||||
for (j = k = 0; j < rel_shdr->sh_size; j += tsize, k++) {
|
||||
len = r_buf_fread_at (bin->b, rel_shdr->sh_offset + j, (ut8*)&rel[k],
|
||||
#if R_BIN_ELF64
|
||||
bin->endian?"2L":"2l",
|
||||
#else
|
||||
bin->endian?"2I":"2i",
|
||||
#endif
|
||||
1);
|
||||
if (len == -1) {
|
||||
eprintf ("Warning: read (rel)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (ELF_R_SYM (rel[k].r_info) == sym) {
|
||||
if (r_buf_read_at (bin->b, rel[k].r_offset-got_addr+got_offset,
|
||||
(ut8*)&plt_sym_addr, sizeof (Elf_(Addr))) == -1) {
|
||||
eprintf ("Warning: read (got)\n");
|
||||
break;
|
||||
}
|
||||
plt_sym_addr -= 6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(rel);
|
||||
return plt_sym_addr;
|
||||
}
|
||||
|
||||
int Elf_(r_bin_elf_has_nx)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
@ -322,29 +290,25 @@ int Elf_(r_bin_elf_has_relro)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
|
||||
ut64 Elf_(r_bin_elf_get_baddr)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
int i;
|
||||
if (!bin->phdr) {
|
||||
//eprintf ("r_bin_elf: canot get_baddr() because no phdr found\n");
|
||||
if (!bin->phdr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hopefully.. the first PT_LOAD is base */
|
||||
for (i = 0; i < bin->ehdr.e_phnum; i++)
|
||||
if (bin->phdr[i].p_type == PT_LOAD)
|
||||
return (ut64)bin->phdr[i].p_vaddr;
|
||||
//eprintf ("oh fuck .. cant find any valid ptload?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ut64 Elf_(r_bin_elf_get_boffset)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
int i;
|
||||
if (!bin->phdr) {
|
||||
//eprintf ("r_bin_elf: canot get_baddr() because no phdr found\n");
|
||||
if (!bin->phdr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hopefully.. the first PT_LOAD is base */
|
||||
for (i = 0; i < bin->ehdr.e_phnum; i++)
|
||||
if (bin->phdr[i].p_type == PT_LOAD)
|
||||
return (ut64) bin->phdr[i].p_offset;
|
||||
//eprintf ("oh fuck .. cant find any valid ptload?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -390,7 +354,7 @@ ut64 Elf_(r_bin_elf_get_entry_offset)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
}
|
||||
if (bin->ehdr.e_entry < bin->baddr)
|
||||
return bin->ehdr.e_entry;
|
||||
return bin->ehdr.e_entry - bin->baddr;
|
||||
return bin->ehdr.e_entry - bin->baddr;
|
||||
}
|
||||
|
||||
ut64 Elf_(r_bin_elf_get_main_offset)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
@ -626,7 +590,7 @@ static inline int noodle(struct Elf_(r_bin_elf_obj_t) *bin, const char *s) {
|
||||
}
|
||||
static inline int needle(struct Elf_(r_bin_elf_obj_t) *bin, const char *s) {
|
||||
if (bin->shstrtab) {
|
||||
int len = bin->shstrtab_size;
|
||||
ut32 len = bin->shstrtab_size;
|
||||
if (len > 4096) len = 4096; // avoid slow loading .. can be buggy?
|
||||
return r_mem_mem ((const ut8*)bin->shstrtab, len,
|
||||
(const ut8*)s, strlen (s)) != NULL;
|
||||
@ -748,6 +712,11 @@ struct r_bin_elf_reloc_t* Elf_(r_bin_elf_get_relocs)(struct Elf_(r_bin_elf_obj_t
|
||||
got_offset = 0;
|
||||
for (i = 0, nsym = 0; i < bin->ehdr.e_shnum; i++)
|
||||
if (bin->shdr[i].sh_type == (bin->ehdr.e_type == ET_REL ? SHT_SYMTAB : SHT_DYNSYM)) {
|
||||
|
||||
/* Bad sh_link ! */
|
||||
if(bin->shdr[i].sh_link >= bin->ehdr.e_shnum)
|
||||
continue;
|
||||
|
||||
bin->strtab_section = &bin->shdr[bin->shdr[i].sh_link];
|
||||
tsize = bin->strtab_section? bin->strtab_section->sh_size: 0;
|
||||
if (!tsize) continue;
|
||||
@ -1064,7 +1033,7 @@ if (
|
||||
ret[ret_ctr].offset = toffset; //(toffset >= bin->baddr ? toffset -= bin->baddr : toffset);
|
||||
ret[ret_ctr].size = tsize;
|
||||
if (sym[k].st_name > strtab_section->sh_size) {
|
||||
perror ("index out of strtab range\n");
|
||||
eprintf ("Warning: index out of strtab range\n");
|
||||
free (ret);
|
||||
free (sym);
|
||||
free (strtab);
|
||||
|
@ -655,6 +655,104 @@ R_API void r_strbuf_init(RStrBuf *sb);
|
||||
R_API char **r_sys_get_environ ();
|
||||
R_API void r_sys_set_environ (char **e);
|
||||
|
||||
|
||||
/* Some "secured" functions, to do basic operation (mul, sub, add...) on integers */
|
||||
static inline int UT64_ADD(ut64 *r, ut64 a, ut64 b) {
|
||||
if(UT64_MAX - a < b)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a + b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int UT64_MUL(ut64 *r, ut64 a, ut64 b) {
|
||||
if(UT64_MAX / a < b)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a * b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int UT64_SUB(ut64 *r, ut64 a, ut64 b) {
|
||||
if(b > a)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a - b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int UT32_ADD(ut32 *r, ut32 a, ut32 b) {
|
||||
if(UT32_MAX - a < b)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a + b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int UT32_MUL(ut32 *r, ut32 a, ut32 b) {
|
||||
if(UT32_MAX / a < b)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a * b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int UT32_SUB(ut32 *r, ut32 a, ut32 b) {
|
||||
if(b > a)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a - b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int UT16_ADD(ut16 *r, ut16 a, ut16 b) {
|
||||
if(UT16_MAX - a < b)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a + b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int UT16_MUL(ut16 *r, ut16 a, ut16 b) {
|
||||
if(UT16_MAX / a < b)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a * b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int UT16_SUB(ut16 *r, ut16 a, ut16 b) {
|
||||
if(b > a)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a - b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int UT8_ADD(ut8 *r, ut8 a, ut8 b) {
|
||||
if(UT8_MAX - a < b)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a + b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int UT8_MUL(ut8 *r, ut8 a, ut8 b) {
|
||||
if(UT8_MAX / a < b)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a * b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int UT8_SUB(ut8 *r, ut8 a, ut8 b) {
|
||||
if(b > a)
|
||||
return 0;
|
||||
if(r != NULL)
|
||||
*r = a - b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -177,7 +177,8 @@ static int r_buf_cpy(RBuffer *b, ut64 addr, ut8 *dst, const ut8 *src, int len, i
|
||||
}
|
||||
|
||||
static int r_buf_fcpy_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int n, int write) {
|
||||
int i, j, k, len, tsize, endian, m = 1;
|
||||
ut64 len, check_len;
|
||||
int i, j, k, tsize, endian, m = 1;
|
||||
if (!b || b->empty) return 0;
|
||||
if (addr == R_BUF_CUR)
|
||||
addr = b->cur;
|
||||
@ -186,8 +187,7 @@ static int r_buf_fcpy_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int
|
||||
return -1;
|
||||
for (i = len = 0; i < n; i++)
|
||||
for (j = 0; fmt[j]; j++) {
|
||||
if (len > b->length)
|
||||
return -1;
|
||||
|
||||
switch (fmt[j]) {
|
||||
case '0'...'9':
|
||||
if (m == 1)
|
||||
@ -202,6 +202,18 @@ static int r_buf_fcpy_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int
|
||||
case 'c': tsize = 1; endian = 1; 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 > b->length)
|
||||
return -1;
|
||||
|
||||
for (k = 0; k < m; k++) {
|
||||
if (write) r_mem_copyendian(
|
||||
(ut8*)&buf[addr+len+k*tsize],
|
||||
@ -210,7 +222,7 @@ static int r_buf_fcpy_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int
|
||||
(ut8*)&buf[len+k*tsize],
|
||||
(ut8*)&b->buf[addr+len+k*tsize], tsize, endian);
|
||||
}
|
||||
len += m*tsize; m = 1;
|
||||
len += tsize*m; m = 1;
|
||||
}
|
||||
b->cur = addr + len;
|
||||
return len;
|
||||
|
Loading…
Reference in New Issue
Block a user