summaryrefslogtreecommitdiffstats
path: root/rtemstoolkit/elftoolchain/libelf/elf_data.c
diff options
context:
space:
mode:
Diffstat (limited to 'rtemstoolkit/elftoolchain/libelf/elf_data.c')
-rw-r--r--rtemstoolkit/elftoolchain/libelf/elf_data.c105
1 files changed, 67 insertions, 38 deletions
diff --git a/rtemstoolkit/elftoolchain/libelf/elf_data.c b/rtemstoolkit/elftoolchain/libelf/elf_data.c
index 5ac6453..d494eda 100644
--- a/rtemstoolkit/elftoolchain/libelf/elf_data.c
+++ b/rtemstoolkit/elftoolchain/libelf/elf_data.c
@@ -27,21 +27,26 @@
#include <assert.h>
#include <errno.h>
#include <libelf.h>
+#include <stdint.h>
#include <stdlib.h>
#include "_libelf.h"
-LIBELF_VCSID("$Id: elf_data.c 1765 2011-08-22 05:59:05Z jkoshy $");
+ELFTC_VCSID("$Id: elf_data.c 3466 2016-05-11 18:35:44Z emaste $");
Elf_Data *
-elf_getdata(Elf_Scn *s, Elf_Data *d)
+elf_getdata(Elf_Scn *s, Elf_Data *ed)
{
Elf *e;
- size_t fsz, msz, count;
- int elfclass, elftype;
unsigned int sh_type;
+ int elfclass, elftype;
+ size_t count, fsz, msz;
+ struct _Libelf_Data *d;
uint64_t sh_align, sh_offset, sh_size;
- int (*xlate)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap);
+ int (*xlate)(unsigned char *_d, size_t _dsz, unsigned char *_s,
+ size_t _c, int _swap);
+
+ d = (struct _Libelf_Data *) ed;
if (s == NULL || (e = s->s_elf) == NULL ||
(d != NULL && s != d->d_scn)) {
@@ -52,10 +57,10 @@ elf_getdata(Elf_Scn *s, Elf_Data *d)
assert(e->e_kind == ELF_K_ELF);
if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL)
- return (d);
+ return (&d->d_data);
if (d != NULL)
- return (STAILQ_NEXT(d, d_next));
+ return (&STAILQ_NEXT(d, d_next)->d_data);
if (e->e_rawfile == NULL) {
/*
@@ -89,7 +94,7 @@ elf_getdata(Elf_Scn *s, Elf_Data *d)
if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
- sh_offset + sh_size > (uint64_t) e->e_rawsize)) {
+ (sh_offset > e->e_rawsize || sh_size > e->e_rawsize - sh_offset))) {
LIBELF_SET_ERROR(SECTION, 0);
return (NULL);
}
@@ -105,28 +110,40 @@ elf_getdata(Elf_Scn *s, Elf_Data *d)
return (NULL);
}
- count = sh_size / fsz;
+ if (sh_size / fsz > SIZE_MAX) {
+ LIBELF_SET_ERROR(RANGE, 0);
+ return (NULL);
+ }
+
+ count = (size_t) (sh_size / fsz);
msz = _libelf_msize(elftype, elfclass, e->e_version);
+ if (count > 0 && msz > SIZE_MAX / count) {
+ LIBELF_SET_ERROR(RANGE, 0);
+ return (NULL);
+ }
+
assert(msz > 0);
+ assert(count <= SIZE_MAX);
+ assert(msz * count <= SIZE_MAX);
if ((d = _libelf_allocate_data(s)) == NULL)
return (NULL);
- d->d_buf = NULL;
- d->d_off = 0;
- d->d_align = sh_align;
- d->d_size = msz * count;
- d->d_type = elftype;
- d->d_version = e->e_version;
+ d->d_data.d_buf = NULL;
+ d->d_data.d_off = 0;
+ d->d_data.d_align = sh_align;
+ d->d_data.d_size = msz * count;
+ d->d_data.d_type = elftype;
+ d->d_data.d_version = e->e_version;
if (sh_type == SHT_NOBITS || sh_size == 0) {
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
- return (d);
+ return (&d->d_data);
}
- if ((d->d_buf = malloc(msz*count)) == NULL) {
+ if ((d->d_data.d_buf = malloc(msz * count)) == NULL) {
(void) _libelf_release_data(d);
LIBELF_SET_ERROR(RESOURCE, 0);
return (NULL);
@@ -135,7 +152,8 @@ elf_getdata(Elf_Scn *s, Elf_Data *d)
d->d_flags |= LIBELF_F_DATA_MALLOCED;
xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass);
- if (!(*xlate)(d->d_buf, d->d_size, e->e_rawfile + sh_offset, count,
+ if (!(*xlate)(d->d_data.d_buf, (size_t) d->d_data.d_size,
+ e->e_rawfile + sh_offset, count,
e->e_byteorder != LIBELF_PRIVATE(byteorder))) {
_libelf_release_data(d);
LIBELF_SET_ERROR(DATA, 0);
@@ -144,14 +162,14 @@ elf_getdata(Elf_Scn *s, Elf_Data *d)
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
- return (d);
+ return (&d->d_data);
}
Elf_Data *
elf_newdata(Elf_Scn *s)
{
Elf *e;
- Elf_Data *d;
+ struct _Libelf_Data *d;
if (s == NULL || (e = s->s_elf) == NULL) {
LIBELF_SET_ERROR(ARGUMENT, 0);
@@ -173,16 +191,16 @@ elf_newdata(Elf_Scn *s)
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
- d->d_align = 1;
- d->d_buf = NULL;
- d->d_off = (uint64_t) ~0;
- d->d_size = 0;
- d->d_type = ELF_T_BYTE;
- d->d_version = LIBELF_PRIVATE(version);
+ d->d_data.d_align = 1;
+ d->d_data.d_buf = NULL;
+ d->d_data.d_off = (uint64_t) ~0;
+ d->d_data.d_size = 0;
+ d->d_data.d_type = ELF_T_BYTE;
+ d->d_data.d_version = LIBELF_PRIVATE(version);
(void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY);
- return (d);
+ return (&d->d_data);
}
/*
@@ -191,11 +209,12 @@ elf_newdata(Elf_Scn *s)
*/
Elf_Data *
-elf_rawdata(Elf_Scn *s, Elf_Data *d)
+elf_rawdata(Elf_Scn *s, Elf_Data *ed)
{
Elf *e;
int elf_class;
uint32_t sh_type;
+ struct _Libelf_Data *d;
uint64_t sh_align, sh_offset, sh_size;
if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) {
@@ -205,11 +224,13 @@ elf_rawdata(Elf_Scn *s, Elf_Data *d)
assert(e->e_kind == ELF_K_ELF);
+ d = (struct _Libelf_Data *) ed;
+
if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL)
- return (d);
+ return (&d->d_data);
if (d != NULL)
- return (STAILQ_NEXT(d, d_next));
+ return (&STAILQ_NEXT(d, d_next)->d_data);
elf_class = e->e_class;
@@ -227,21 +248,29 @@ elf_rawdata(Elf_Scn *s, Elf_Data *d)
sh_align = s->s_shdr.s_shdr64.sh_addralign;
}
- if (sh_type == SHT_NULL)
+ if (sh_type == SHT_NULL) {
+ LIBELF_SET_ERROR(SECTION, 0);
+ return (NULL);
+ }
+
+ if (sh_type != SHT_NOBITS &&
+ (sh_offset > e->e_rawsize || sh_size > e->e_rawsize - sh_offset)) {
+ LIBELF_SET_ERROR(SECTION, 0);
return (NULL);
+ }
if ((d = _libelf_allocate_data(s)) == NULL)
return (NULL);
- d->d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL :
+ d->d_data.d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL :
e->e_rawfile + sh_offset;
- d->d_off = 0;
- d->d_align = sh_align;
- d->d_size = sh_size;
- d->d_type = ELF_T_BYTE;
- d->d_version = e->e_version;
+ d->d_data.d_off = 0;
+ d->d_data.d_align = sh_align;
+ d->d_data.d_size = sh_size;
+ d->d_data.d_type = ELF_T_BYTE;
+ d->d_data.d_version = e->e_version;
STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next);
- return (d);
+ return (&d->d_data);
}