From: Petr Machata Date: Wed, 9 Mar 2011 01:00:28 +0000 (+0100) Subject: dwarflint: Fix a SEGV for invalid address size in CU header X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=90903237e77986f1fd906783ff114eb70b7e7e38;p=thirdparty%2Felfutils.git dwarflint: Fix a SEGV for invalid address size in CU header - read_address_size has a richer interface now. New type error_code, which might be more generally useful - adapt callers - add test case --- diff --git a/dwarflint/check_debug_aranges.cc b/dwarflint/check_debug_aranges.cc index a2fcd450c..915dcae4f 100644 --- a/dwarflint/check_debug_aranges.cc +++ b/dwarflint/check_debug_aranges.cc @@ -1,5 +1,5 @@ /* Low-level checking of .debug_aranges. - Copyright (C) 2009, 2010 Red Hat, Inc. + Copyright (C) 2009, 2010, 2011 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -286,11 +286,12 @@ check_aranges_structural (struct elf_file *file, /* Address size. */ int address_size; - if (!read_address_size (&sub_ctx, file->addr_64, &address_size, &where)) - { - retval = false; - goto next; - } + error_code err = read_address_size (&sub_ctx, file->addr_64, + &address_size, &where); + if (err != err_ok) + retval = false; + if (err == err_fatal) + goto next; /* Segment size. */ uint8_t segment_size; diff --git a/dwarflint/check_debug_info.cc b/dwarflint/check_debug_info.cc index 984d60876..45af96b85 100644 --- a/dwarflint/check_debug_info.cc +++ b/dwarflint/check_debug_info.cc @@ -174,6 +174,7 @@ namespace struct read_ctx ctx; read_ctx_init (&ctx, sec->data, file->other_byte_order); uint64_t off_start, off_end; + bool fail = false; std::vector ret; while (!read_ctx_eof (&ctx)) @@ -278,9 +279,12 @@ namespace << pri::lacks_relocation ("abbrev table offset") << std::endl; /* Address size. */ - if (!read_address_size (&ctx, file->addr_64, &head.address_size, - &head.where)) + error_code err = read_address_size (&ctx, file->addr_64, + &head.address_size, &head.where); + if (err == err_fatal) throw check_base::failed (); + else if (err == err_nohl) + fail = true; head.head_size = ctx.ptr - cu_begin; // Length of the headers itself. head.total_size = cu_end - cu_begin; // Length including headers field. @@ -295,6 +299,9 @@ namespace ret.push_back (head); } + if (fail) + throw check_base::failed (); + return ret; } diff --git a/dwarflint/checked_read.cc b/dwarflint/checked_read.cc index c6a714454..14831ecb1 100644 --- a/dwarflint/checked_read.cc +++ b/dwarflint/checked_read.cc @@ -1,5 +1,5 @@ /* Pedantic checking of DWARF files - Copyright (C) 2010 Red Hat, Inc. + Copyright (C) 2010, 2011 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -66,7 +66,7 @@ read_size_extra (struct read_ctx *ctx, uint32_t size32, uint64_t *sizep, return true; } -bool +error_code read_address_size (struct read_ctx *ctx, bool addr_64, int *address_sizep, @@ -76,9 +76,10 @@ read_address_size (struct read_ctx *ctx, if (!read_ctx_read_ubyte (ctx, &address_size)) { wr_error (where, ": can't read address size.\n"); - return false; + return err_fatal; } + error_code ret = err_ok; if (address_size != 4 && address_size != 8) { /* Keep going. Deduce the address size from ELF header, and try @@ -87,15 +88,19 @@ read_address_size (struct read_ctx *ctx, ": invalid address size: %d (only 4 or 8 allowed).\n", address_size); address_size = addr_64 ? 8 : 4; + ret = err_nohl; } else if ((address_size == 8) != addr_64) - /* Keep going, we may still be able to parse it. */ - wr_error (where, - ": CU reports address size of %d in %d-bit ELF.\n", - address_size, addr_64 ? 64 : 32); + { + /* Keep going, we may still be able to parse it. */ + wr_error (where, + ": CU reports address size of %d in %d-bit ELF.\n", + address_size, addr_64 ? 64 : 32); + ret = err_nohl; + } *address_sizep = address_size; - return true; + return ret; } bool diff --git a/dwarflint/checked_read.hh b/dwarflint/checked_read.hh index 4171b57a6..1e0deda8c 100644 --- a/dwarflint/checked_read.hh +++ b/dwarflint/checked_read.hh @@ -1,5 +1,5 @@ /* Pedantic checking of DWARF files - Copyright (C) 2010 Red Hat, Inc. + Copyright (C) 2010, 2011 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -30,13 +30,23 @@ #include "where.h" #include "dwarf_version.hh" +enum error_code + { + err_ok, ///< The operation passed. + err_fatal, ///< The operation ended in unrecoverable error. + err_nohl, ///< There was an error, but low-level checks may continue. + }; + bool read_size_extra (read_ctx *ctx, uint32_t size32, uint64_t *sizep, int *offset_sizep, where *where); -bool read_address_size (read_ctx *ctx, - bool addr_64, - int *address_sizep, - where const *where); +/// Read address size and return it via address_sizep and return 0. +/// Address size may be 4 or 8; for other values it's set depending or +/// addr_64, and err_nohl is returned. +error_code read_address_size (read_ctx *ctx, + bool addr_64, + int *address_sizep, + where const *where); bool checked_read_uleb128 (read_ctx *ctx, uint64_t *ret, where const *where, const char *what); diff --git a/dwarflint/tests/garbage-6.bz2 b/dwarflint/tests/garbage-6.bz2 new file mode 100644 index 000000000..6cb8a44b6 Binary files /dev/null and b/dwarflint/tests/garbage-6.bz2 differ diff --git a/dwarflint/tests/run-bad.sh b/dwarflint/tests/run-bad.sh index 2da33b651..108f527bb 100755 --- a/dwarflint/tests/run-bad.sh +++ b/dwarflint/tests/run-bad.sh @@ -28,7 +28,7 @@ srcdir=$srcdir/tests testfiles hello.bad-1 hello.bad-3 garbage-1 garbage-2 garbage-3 garbage-4 \ - garbage-5 + garbage-5 garbage-6 testrun_compare ./dwarflint hello.bad-1 <