gelf_fsize, elf32_fsize and elf64_fsize return count * sizeof type as
size_t, or zero to indicate an error. Check count is zero or count
times size would overflow and fail with libelf errno set to
ELF_E_INVALID_OPERAND in that case.

        * libelf/elf32_fsize.c (elf32_fsize): Check whether count is
        zero or count times size would overflow.
        * libelf/gelf_fsize.c (gelf_fsize): Likewise.

Signed-off-by: Mark Wielaard <[email protected]>
---
 libelf/elf32_fsize.c | 10 +++++++++-
 libelf/gelf_fsize.c  | 10 +++++++++-
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/libelf/elf32_fsize.c b/libelf/elf32_fsize.c
index 139f4a91ce78..d48fde3df320 100644
--- a/libelf/elf32_fsize.c
+++ b/libelf/elf32_fsize.c
@@ -56,5 +56,13 @@ elfw2(LIBELFBITS, fsize) (Elf_Type type, size_t count, 
unsigned int version)
       return 0;
     }
 
-  return (count * __libelf_type_sizes[ELFW(ELFCLASS,LIBELFBITS) - 1][type]);
+  size_t size = __libelf_type_sizes[ELFW(ELFCLASS,LIBELFBITS) - 1][type];
+
+  if (unlikely (count == 0 || count > SIZE_MAX / size))
+    {
+      __libelf_seterrno (ELF_E_INVALID_OPERAND);
+      return 0;
+    }
+
+  return count * size;
 }
diff --git a/libelf/gelf_fsize.c b/libelf/gelf_fsize.c
index 371f08f2cc2c..ba4a8e880f74 100644
--- a/libelf/gelf_fsize.c
+++ b/libelf/gelf_fsize.c
@@ -107,7 +107,15 @@ gelf_fsize (Elf *elf, Elf_Type type, size_t count, 
unsigned int version)
       return 0;
     }
 
-  return count * __libelf_type_sizes[elf->class - 1][type];
+  size_t size = __libelf_type_sizes[elf->class - 1][type];
+
+  if (count == 0 || count > SIZE_MAX / size)
+    {
+      __libelf_seterrno (ELF_E_INVALID_OPERAND);
+      return 0;
+    }
+
+  return count * size;
 }
 INTDEF(gelf_fsize)
 
-- 
2.56.0

Reply via email to