From 5fef17c05dd20ea6c0a6e3532177a916ef022a3c Mon Sep 17 00:00:00 2001 From: Tommi Rantala Date: Sun, 5 Aug 2012 18:22:21 +0300 Subject: [PATCH] Fix memory leaks in unw_create_addr_space() wrong-endian error paths Check the endianness earlier in unw_create_addr_space() on all architectures to avoid leaking the dynamically allocated address space struct. This was already fixed for ARM in commit cf6a99879604 ("Fix memory leak in ARM unw_create_addr_space()"). Move the endianness check also on ARM to avoid malloc() & free() in the error case. --- src/arm/Gcreate_addr_space.c | 20 +++++++++----------- src/hppa/Gcreate_addr_space.c | 14 ++++++++------ src/mips/Gcreate_addr_space.c | 17 +++++++++-------- src/ppc/Gcreate_addr_space.c | 14 ++++++++------ src/x86/Gcreate_addr_space.c | 14 ++++++++------ src/x86_64/Gcreate_addr_space.c | 15 +++++++++------ 6 files changed, 51 insertions(+), 43 deletions(-) diff --git a/src/arm/Gcreate_addr_space.c b/src/arm/Gcreate_addr_space.c index 53746491..4d59a20a 100644 --- a/src/arm/Gcreate_addr_space.c +++ b/src/arm/Gcreate_addr_space.c @@ -32,8 +32,16 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) #ifdef UNW_LOCAL_ONLY return NULL; #else - unw_addr_space_t as = malloc (sizeof (*as)); + unw_addr_space_t as; + /* + * ARM supports little-endian and big-endian. + */ + if (byte_order != 0 && byte_order != __LITTLE_ENDIAN + && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); if (!as) return NULL; @@ -41,16 +49,6 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) as->acc = *a; - /* - * ARM supports little-endian and big-endian. - */ - if (byte_order != 0 && byte_order != __LITTLE_ENDIAN - && byte_order != __BIG_ENDIAN) - { - free(as); - return NULL; - } - /* Default to little-endian for ARM. */ if (byte_order == 0 || byte_order == __LITTLE_ENDIAN) as->big_endian = 0; diff --git a/src/hppa/Gcreate_addr_space.c b/src/hppa/Gcreate_addr_space.c index 8f4301fe..ecc805dc 100644 --- a/src/hppa/Gcreate_addr_space.c +++ b/src/hppa/Gcreate_addr_space.c @@ -33,8 +33,15 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) #ifdef UNW_LOCAL_ONLY return NULL; #else - unw_addr_space_t as = malloc (sizeof (*as)); + unw_addr_space_t as; + /* + * hppa supports only big-endian. + */ + if (byte_order != 0 && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); if (!as) return NULL; @@ -42,11 +49,6 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) as->acc = *a; - /* - * hppa supports only big-endian. - */ - if (byte_order != 0 && byte_order != __BIG_ENDIAN) - return NULL; return as; #endif } diff --git a/src/mips/Gcreate_addr_space.c b/src/mips/Gcreate_addr_space.c index af084ef0..371841d9 100644 --- a/src/mips/Gcreate_addr_space.c +++ b/src/mips/Gcreate_addr_space.c @@ -32,14 +32,7 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) #ifdef UNW_LOCAL_ONLY return NULL; #else - unw_addr_space_t as = malloc (sizeof (*as)); - - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; + unw_addr_space_t as; /* * MIPS supports only big or little-endian, not weird stuff like @@ -50,6 +43,14 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) && byte_order != __BIG_ENDIAN) return NULL; + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + if (byte_order == 0) /* use host default: */ as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); diff --git a/src/ppc/Gcreate_addr_space.c b/src/ppc/Gcreate_addr_space.c index 21ec10fc..09bde565 100644 --- a/src/ppc/Gcreate_addr_space.c +++ b/src/ppc/Gcreate_addr_space.c @@ -35,8 +35,15 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) #ifdef UNW_LOCAL_ONLY return NULL; #else - unw_addr_space_t as = malloc (sizeof (*as)); + unw_addr_space_t as; + /* + * Linux ppc64 supports only big-endian. + */ + if (byte_order != 0 && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); if (!as) return NULL; @@ -44,11 +51,6 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) as->acc = *a; - /* - * Linux ppc64 supports only big-endian. - */ - if (byte_order != 0 && byte_order != __BIG_ENDIAN) - return NULL; return as; #endif } diff --git a/src/x86/Gcreate_addr_space.c b/src/x86/Gcreate_addr_space.c index 5dd6367a..5b07940d 100644 --- a/src/x86/Gcreate_addr_space.c +++ b/src/x86/Gcreate_addr_space.c @@ -37,8 +37,15 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) #ifdef UNW_LOCAL_ONLY return NULL; #else - unw_addr_space_t as = malloc (sizeof (*as)); + unw_addr_space_t as; + /* + * x86 supports only little-endian. + */ + if (byte_order != 0 && byte_order != __LITTLE_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); if (!as) return NULL; @@ -46,11 +53,6 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) as->acc = *a; - /* - * x86 supports only little-endian. - */ - if (byte_order != 0 && byte_order != __LITTLE_ENDIAN) - return NULL; return as; #endif } diff --git a/src/x86_64/Gcreate_addr_space.c b/src/x86_64/Gcreate_addr_space.c index 02b93ebb..aab126a4 100644 --- a/src/x86_64/Gcreate_addr_space.c +++ b/src/x86_64/Gcreate_addr_space.c @@ -3,6 +3,7 @@ Contributed by David Mosberger-Tang Modified for x86_64 by Max Asbock + Copyright (C) 2012 Tommi Rantala This file is part of libunwind. @@ -39,8 +40,15 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) #ifdef UNW_LOCAL_ONLY return NULL; #else - unw_addr_space_t as = malloc (sizeof (*as)); + unw_addr_space_t as; + /* + * x86_64 supports only little-endian. + */ + if (byte_order != 0 && byte_order != __LITTLE_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); if (!as) return NULL; @@ -48,11 +56,6 @@ unw_create_addr_space (unw_accessors_t *a, int byte_order) as->acc = *a; - /* - * x86_64 supports only little-endian. - */ - if (byte_order != 0 && byte_order != __LITTLE_ENDIAN) - return NULL; return as; #endif }