Add ELF_E_INVALID_ELF which is set when the ELF file data is bad.
This is different from ELF_E_INVALID_FILE which is set when the file
could not be read.
Signed-off-by: Mark Wielaard <mark@klomp.org>
+2017-10-04 Mark Wielaard <mark@klomp.org>
+
+ * libelfP.h: Add ELF_E_INVALID_ELF to error values enum.
+ * elf_error.c (ELF_E_INVALID_ELF_IDX): New define. Use it as value
+ for ELF_E_INVALID_ELF in msgidx.
+ * elf_getshdrstrndx.c (elf_getshdrstrndx): Distinquish between pread
+ failing and not having enough data.
+ * elf_begin.c (get_shnum): Likewise. Explicitly set libelf errno on
+ too large value.
+ (file_read_elf): Make sure to always set libelf errno when returning
+ NULL. Distinquish between i/o file and elf data errors.
+
2017-08-18 Ulf Hermann <ulf.hermann@qt.io>
* gelf_xlate.c: Use attribute_packed.
else
{
Elf32_Word size;
+ ssize_t r;
if (likely (map_address != NULL))
/* gcc will optimize the memcpy to a simple memory
+ offset))->sh_size,
sizeof (Elf32_Word));
else
- if (unlikely (pread_retry (fildes, &size, sizeof (Elf32_Word),
- offset + ehdr.e32->e_shoff
- + offsetof (Elf32_Shdr, sh_size))
+ if (unlikely ((r = pread_retry (fildes, &size,
+ sizeof (Elf32_Word),
+ offset + ehdr.e32->e_shoff
+ + offsetof (Elf32_Shdr,
+ sh_size)))
!= sizeof (Elf32_Word)))
- return (size_t) -1l;
+ {
+ if (r < 0)
+ __libelf_seterrno (ELF_E_INVALID_FILE);
+ else
+ __libelf_seterrno (ELF_E_INVALID_ELF);
+ return (size_t) -1l;
+ }
if (e_ident[EI_DATA] != MY_ELFDATA)
CONVERT (size);
+ offset))->sh_size;
else
{
+ ssize_t r;
if (likely (map_address != NULL))
/* gcc will optimize the memcpy to a simple memory
access while taking care of alignment issues. */
+ offset))->sh_size,
sizeof (Elf64_Xword));
else
- if (unlikely (pread_retry (fildes, &size, sizeof (Elf64_Xword),
- offset + ehdr.e64->e_shoff
- + offsetof (Elf64_Shdr, sh_size))
+ if (unlikely ((r = pread_retry (fildes, &size,
+ sizeof (Elf64_Xword),
+ offset + ehdr.e64->e_shoff
+ + offsetof (Elf64_Shdr,
+ sh_size)))
!= sizeof (Elf64_Xword)))
- return (size_t) -1l;
+ {
+ if (r < 0)
+ __libelf_seterrno (ELF_E_INVALID_FILE);
+ else
+ __libelf_seterrno (ELF_E_INVALID_ELF);
+ return (size_t) -1l;
+ }
if (e_ident[EI_DATA] != MY_ELFDATA)
CONVERT (size);
}
if (size > ~((GElf_Word) 0))
- /* Invalid value, it is too large. */
- return (size_t) -1l;
+ {
+ /* Invalid value, it is too large. */
+ __libelf_seterrno (ELF_E_INVALID_ELF);
+ return (size_t) -1l;
+ }
result = size;
}
&& e_ident[EI_DATA] != ELFDATA2MSB)))
{
/* Cannot handle this. */
- __libelf_seterrno (ELF_E_INVALID_FILE);
+ __libelf_seterrno (ELF_E_INVALID_ELF);
return NULL;
}
- /* Determine the number of sections. */
+ /* Determine the number of sections. Returns -1 and sets libelf errno
+ if the file handle or elf file is invalid. Returns zero if there
+ are no section headers (or they cannot be read). */
size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize);
if (scncnt == (size_t) -1l)
/* Could not determine the number of sections. */
if (e_ident[EI_CLASS] == ELFCLASS32)
{
if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr)))
- return NULL;
+ {
+ __libelf_seterrno (ELF_E_INVALID_ELF);
+ return NULL;
+ }
}
else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr)))
- return NULL;
+ {
+ __libelf_seterrno (ELF_E_INVALID_ELF);
+ return NULL;
+ }
/* We can now allocate the memory. Even if there are no section headers,
we allocate space for a zeroth section in case we need it later. */
Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
ELF_K_ELF, scnmax * sizeof (Elf_Scn));
if (elf == NULL)
- /* Not enough memory. */
+ /* Not enough memory. allocate_elf will have set libelf errno. */
return NULL;
assert ((unsigned int) scncnt == scncnt);
{
free_and_out:
free (elf);
- __libelf_seterrno (ELF_E_INVALID_FILE);
+ __libelf_seterrno (ELF_E_INVALID_ELF);
return NULL;
}
elf->state.elf32.shdr
(ELF_E_NOMEM_IDX + sizeof "out of memory")
N_("invalid file descriptor")
"\0"
-#define ELF_E_INVALID_OP_IDX \
+#define ELF_E_INVALID_ELF_IDX \
(ELF_E_INVALID_FILE_IDX + sizeof "invalid file descriptor")
+ N_("invalid ELF file data")
+ "\0"
+#define ELF_E_INVALID_OP_IDX \
+ (ELF_E_INVALID_ELF_IDX + sizeof "invalid ELF file data")
N_("invalid operation")
"\0"
#define ELF_E_NO_VERSION_IDX \
[ELF_E_INVALID_ENCODING] = ELF_E_INVALID_ENCODING_IDX,
[ELF_E_NOMEM] = ELF_E_NOMEM_IDX,
[ELF_E_INVALID_FILE] = ELF_E_INVALID_FILE_IDX,
+ [ELF_E_INVALID_ELF] = ELF_E_INVALID_ELF_IDX,
[ELF_E_INVALID_OP] = ELF_E_INVALID_OP_IDX,
[ELF_E_NO_VERSION] = ELF_E_NO_VERSION_IDX,
[ELF_E_INVALID_CMD] = ELF_E_INVALID_CMD_IDX,
/* We avoid reading in all the section headers. Just read
the first one. */
Elf32_Shdr shdr_mem;
+ ssize_t r;
- if (unlikely (pread_retry (elf->fildes, &shdr_mem,
- sizeof (Elf32_Shdr), offset)
+ if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
+ sizeof (Elf32_Shdr), offset))
!= sizeof (Elf32_Shdr)))
{
/* We must be able to read this ELF section header. */
- __libelf_seterrno (ELF_E_INVALID_FILE);
+ if (r < 0)
+ __libelf_seterrno (ELF_E_INVALID_FILE);
+ else
+ __libelf_seterrno (ELF_E_INVALID_ELF);
result = -1;
goto out;
}
/* We avoid reading in all the section headers. Just read
the first one. */
Elf64_Shdr shdr_mem;
+ ssize_t r;
- if (unlikely (pread_retry (elf->fildes, &shdr_mem,
- sizeof (Elf64_Shdr), offset)
+ if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
+ sizeof (Elf64_Shdr), offset))
!= sizeof (Elf64_Shdr)))
{
/* We must be able to read this ELF section header. */
- __libelf_seterrno (ELF_E_INVALID_FILE);
+ if (r < 0)
+ __libelf_seterrno (ELF_E_INVALID_FILE);
+ else
+ __libelf_seterrno (ELF_E_INVALID_ELF);
result = -1;
goto out;
}
ELF_E_INVALID_ENCODING,
ELF_E_NOMEM,
ELF_E_INVALID_FILE,
+ ELF_E_INVALID_ELF,
ELF_E_INVALID_OP,
ELF_E_NO_VERSION,
ELF_E_INVALID_CMD,
+2017-10-04 Mark Wielaard <mark@klomp.org>
+
+ * msg_tst.c: Handle ELF_E_INVALID_ELF.
+
2017-09-10 Mark Wielaard <mark@klomp.org>
* run-ar.sh: New test.
{ ELF_E_INVALID_ENCODING, "invalid encoding" },
{ ELF_E_NOMEM, "out of memory" },
{ ELF_E_INVALID_FILE, "invalid file descriptor" },
+ { ELF_E_INVALID_ELF, "invalid ELF file data" },
{ ELF_E_INVALID_OP, "invalid operation" },
{ ELF_E_NO_VERSION, "ELF version not set" },
{ ELF_E_INVALID_CMD, "invalid command" },