| From 8e2f54bcee7e3e8315d4a39a302eaf8e4389e07d Mon Sep 17 00:00:00 2001 |
| From: "H.J. Lu" <hjl.tools@gmail.com> |
| Date: Tue, 30 May 2017 06:34:05 -0700 |
| Subject: [PATCH] Add bfd_get_file_size to get archive element size |
| |
| We can't use stat() to get archive element size. Add bfd_get_file_size |
| to get size for both normal files and archive elements. |
| |
| bfd/ |
| |
| PR binutils/21519 |
| * bfdio.c (bfd_get_file_size): New function. |
| * bfd-in2.h: Regenerated. |
| |
| binutils/ |
| |
| PR binutils/21519 |
| * objdump.c (dump_relocs_in_section): Replace get_file_size |
| with bfd_get_file_size to get archive element size. |
| * testsuite/binutils-all/objdump.exp (test_objdump_f): New |
| proc. |
| (test_objdump_h): Likewise. |
| (test_objdump_t): Likewise. |
| (test_objdump_r): Likewise. |
| (test_objdump_s): Likewise. |
| Add objdump tests on archive. |
| |
| Upstream-Status: Backport |
| CVE: CVE-2017-9955 |
| Signed-off-by: Armin Kuster <akuster@mvista.com> |
| |
| --- |
| bfd/ChangeLog | 6 + |
| bfd/bfd-in2.h | 2 + |
| bfd/bfdio.c | 23 ++++ |
| binutils/ChangeLog | 13 ++ |
| binutils/objdump.c | 2 +- |
| binutils/testsuite/binutils-all/objdump.exp | 178 +++++++++++++++++++--------- |
| 6 files changed, 170 insertions(+), 54 deletions(-) |
| |
| Index: git/bfd/bfd-in2.h |
| =================================================================== |
| --- git.orig/bfd/bfd-in2.h |
| +++ git/bfd/bfd-in2.h |
| @@ -1241,6 +1241,8 @@ long bfd_get_mtime (bfd *abfd); |
| |
| file_ptr bfd_get_size (bfd *abfd); |
| |
| +file_ptr bfd_get_file_size (bfd *abfd); |
| + |
| void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len, |
| int prot, int flags, file_ptr offset, |
| void **map_addr, bfd_size_type *map_len); |
| Index: git/bfd/bfdio.c |
| =================================================================== |
| --- git.orig/bfd/bfdio.c |
| +++ git/bfd/bfdio.c |
| @@ -434,6 +434,29 @@ bfd_get_size (bfd *abfd) |
| return buf.st_size; |
| } |
| |
| +/* |
| +FUNCTION |
| + bfd_get_file_size |
| + |
| +SYNOPSIS |
| + file_ptr bfd_get_file_size (bfd *abfd); |
| + |
| +DESCRIPTION |
| + Return the file size (as read from file system) for the file |
| + associated with BFD @var{abfd}. It supports both normal files |
| + and archive elements. |
| + |
| +*/ |
| + |
| +file_ptr |
| +bfd_get_file_size (bfd *abfd) |
| +{ |
| + if (abfd->my_archive != NULL |
| + && !bfd_is_thin_archive (abfd->my_archive)) |
| + return arelt_size (abfd); |
| + |
| + return bfd_get_size (abfd); |
| +} |
| |
| /* |
| FUNCTION |
| Index: git/binutils/objdump.c |
| =================================================================== |
| --- git.orig/binutils/objdump.c |
| +++ git/binutils/objdump.c |
| @@ -3310,7 +3310,7 @@ dump_relocs_in_section (bfd *abfd, |
| } |
| |
| if ((bfd_get_file_flags (abfd) & (BFD_IN_MEMORY | BFD_LINKER_CREATED)) == 0 |
| - && relsize > get_file_size (bfd_get_filename (abfd))) |
| + && relsize > bfd_get_file_size (abfd)) |
| { |
| printf (" (too many: 0x%x)\n", section->reloc_count); |
| bfd_set_error (bfd_error_file_truncated); |
| Index: git/binutils/testsuite/binutils-all/objdump.exp |
| =================================================================== |
| --- git.orig/binutils/testsuite/binutils-all/objdump.exp |
| +++ git/binutils/testsuite/binutils-all/objdump.exp |
| @@ -64,96 +64,168 @@ if [regexp $want $got] then { |
| if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { |
| return |
| } |
| +if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest2.o]} then { |
| + return |
| +} |
| if [is_remote host] { |
| set testfile [remote_download host tmpdir/bintest.o] |
| + set testfile2 [remote_download host tmpdir/bintest2.o] |
| } else { |
| set testfile tmpdir/bintest.o |
| + set testfile2 tmpdir/bintest2.o |
| +} |
| + |
| +if { ![istarget "alpha-*-*"] || [is_elf_format] } then { |
| + remote_file host file delete tmpdir/bintest.a |
| + set got [binutils_run $AR "rc tmpdir/bintest.a $testfile2"] |
| + if ![string match "" $got] then { |
| + fail "bintest.a" |
| + remote_file host delete tmpdir/bintest.a |
| + } else { |
| + if [is_remote host] { |
| + set testarchive [remote_download host tmpdir/bintest.a] |
| + } else { |
| + set testarchive tmpdir/bintest.a |
| + } |
| + } |
| + remote_file host delete tmpdir/bintest2.o |
| } |
| |
| # Test objdump -f |
| |
| -set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f $testfile"] |
| +proc test_objdump_f { testfile dumpfile } { |
| + global OBJDUMP |
| + global OBJDUMPFLAGS |
| + global cpus_regex |
| |
| -set want "$testfile:\[ \]*file format.*architecture:\[ \]*${cpus_regex}.*HAS_RELOC.*HAS_SYMS" |
| + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f $testfile"] |
| |
| -if ![regexp $want $got] then { |
| - fail "objdump -f" |
| -} else { |
| - pass "objdump -f" |
| + set want "$dumpfile:\[ \]*file format.*architecture:\[ \]*${cpus_regex}.*HAS_RELOC.*HAS_SYMS" |
| + |
| + if ![regexp $want $got] then { |
| + fail "objdump -f ($testfile, $dumpfile)" |
| + } else { |
| + pass "objdump -f ($testfile, $dumpfile)" |
| + } |
| +} |
| + |
| +test_objdump_f $testfile $testfile |
| +if { [ remote_file host exists $testarchive ] } then { |
| + test_objdump_f $testarchive bintest2.o |
| } |
| |
| # Test objdump -h |
| |
| -set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h $testfile"] |
| +proc test_objdump_h { testfile dumpfile } { |
| + global OBJDUMP |
| + global OBJDUMPFLAGS |
| |
| -set want "$testfile:\[ \]*file format.*Sections.*\[0-9\]+\[ \]+\[^ \]*(text|TEXT|P|\\\$CODE\\\$)\[^ \]*\[ \]*(\[0-9a-fA-F\]+).*\[0-9\]+\[ \]+\[^ \]*(\\.data|DATA|D_1)\[^ \]*\[ \]*(\[0-9a-fA-F\]+)" |
| + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h $testfile"] |
| |
| -if ![regexp $want $got all text_name text_size data_name data_size] then { |
| - fail "objdump -h" |
| -} else { |
| - verbose "text name is $text_name size is $text_size" |
| - verbose "data name is $data_name size is $data_size" |
| - set ets 8 |
| - set eds 4 |
| - # The [ti]c4x target has the property sizeof(char)=sizeof(long)=1 |
| - if [istarget *c4x*-*-*] then { |
| - set ets 2 |
| - set eds 1 |
| - } |
| - # c54x section sizes are in bytes, not octets; adjust accordingly |
| - if [istarget *c54x*-*-*] then { |
| - set ets 4 |
| - set eds 2 |
| - } |
| - if {[expr "0x$text_size"] < $ets || [expr "0x$data_size"] < $eds} then { |
| - send_log "sizes too small\n" |
| - fail "objdump -h" |
| + set want "$dumpfile:\[ \]*file format.*Sections.*\[0-9\]+\[ \]+\[^ \]*(text|TEXT|P|\\\$CODE\\\$)\[^ \]*\[ \]*(\[0-9a-fA-F\]+).*\[0-9\]+\[ \]+\[^ \]*(\\.data|DATA|D_1)\[^ \]*\[ \]*(\[0-9a-fA-F\]+)" |
| + |
| + if ![regexp $want $got all text_name text_size data_name data_size] then { |
| + fail "objdump -h ($testfile, $dumpfile)" |
| } else { |
| - pass "objdump -h" |
| + verbose "text name is $text_name size is $text_size" |
| + verbose "data name is $data_name size is $data_size" |
| + set ets 8 |
| + set eds 4 |
| + # The [ti]c4x target has the property sizeof(char)=sizeof(long)=1 |
| + if [istarget *c4x*-*-*] then { |
| + set ets 2 |
| + set eds 1 |
| + } |
| + # c54x section sizes are in bytes, not octets; adjust accordingly |
| + if [istarget *c54x*-*-*] then { |
| + set ets 4 |
| + set eds 2 |
| + } |
| + if {[expr "0x$text_size"] < $ets || [expr "0x$data_size"] < $eds} then { |
| + send_log "sizes too small\n" |
| + fail "objdump -h ($testfile, $dumpfile)" |
| + } else { |
| + pass "objdump -h ($testfile, $dumpfile)" |
| + } |
| } |
| } |
| |
| +test_objdump_h $testfile $testfile |
| +if { [ remote_file host exists $testarchive ] } then { |
| + test_objdump_h $testarchive bintest2.o |
| +} |
| + |
| # Test objdump -t |
| |
| -set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -t $testfile"] |
| +proc test_objdump_t { testfile} { |
| + global OBJDUMP |
| + global OBJDUMPFLAGS |
| + |
| + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -t $testfile"] |
| + |
| + if [info exists vars] then { unset vars } |
| + while {[regexp "(\[a-z\]*_symbol)(.*)" $got all symbol rest]} { |
| + set vars($symbol) 1 |
| + set got $rest |
| + } |
| |
| -if [info exists vars] then { unset vars } |
| -while {[regexp "(\[a-z\]*_symbol)(.*)" $got all symbol rest]} { |
| - set vars($symbol) 1 |
| - set got $rest |
| + if {![info exists vars(text_symbol)] \ |
| + || ![info exists vars(data_symbol)] \ |
| + || ![info exists vars(common_symbol)] \ |
| + || ![info exists vars(external_symbol)]} then { |
| + fail "objdump -t ($testfile)" |
| + } else { |
| + pass "objdump -t ($testfile)" |
| + } |
| } |
| |
| -if {![info exists vars(text_symbol)] \ |
| - || ![info exists vars(data_symbol)] \ |
| - || ![info exists vars(common_symbol)] \ |
| - || ![info exists vars(external_symbol)]} then { |
| - fail "objdump -t" |
| -} else { |
| - pass "objdump -t" |
| +test_objdump_t $testfile |
| +if { [ remote_file host exists $testarchive ] } then { |
| + test_objdump_t $testarchive |
| } |
| |
| # Test objdump -r |
| |
| -set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -r $testfile"] |
| +proc test_objdump_r { testfile dumpfile } { |
| + global OBJDUMP |
| + global OBJDUMPFLAGS |
| |
| -set want "$testfile:\[ \]*file format.*RELOCATION RECORDS FOR \\\[\[^\]\]*(text|TEXT|P|\\\$CODE\\\$)\[^\]\]*\\\].*external_symbol" |
| + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -r $testfile"] |
| |
| -if [regexp $want $got] then { |
| - pass "objdump -r" |
| -} else { |
| - fail "objdump -r" |
| + set want "$dumpfile:\[ \]*file format.*RELOCATION RECORDS FOR \\\[\[^\]\]*(text|TEXT|P|\\\$CODE\\\$)\[^\]\]*\\\].*external_symbol" |
| + |
| + if [regexp $want $got] then { |
| + pass "objdump -r ($testfile, $dumpfile)" |
| + } else { |
| + fail "objdump -r ($testfile, $dumpfile)" |
| + } |
| +} |
| + |
| +test_objdump_r $testfile $testfile |
| +if { [ remote_file host exists $testarchive ] } then { |
| + test_objdump_r $testarchive bintest2.o |
| } |
| |
| # Test objdump -s |
| |
| -set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -s $testfile"] |
| +proc test_objdump_s { testfile dumpfile } { |
| + global OBJDUMP |
| + global OBJDUMPFLAGS |
| |
| -set want "$testfile:\[ \]*file format.*Contents.*(text|TEXT|P|\\\$CODE\\\$)\[^0-9\]*\[ \]*\[0-9a-fA-F\]*\[ \]*(00000001|01000000|00000100).*Contents.*(data|DATA|D_1)\[^0-9\]*\[ \]*\[0-9a-fA-F\]*\[ \]*(00000002|02000000|00000200)" |
| + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -s $testfile"] |
| |
| -if [regexp $want $got] then { |
| - pass "objdump -s" |
| -} else { |
| - fail "objdump -s" |
| + set want "$dumpfile:\[ \]*file format.*Contents.*(text|TEXT|P|\\\$CODE\\\$)\[^0-9\]*\[ \]*\[0-9a-fA-F\]*\[ \]*(00000001|01000000|00000100).*Contents.*(data|DATA|D_1)\[^0-9\]*\[ \]*\[0-9a-fA-F\]*\[ \]*(00000002|02000000|00000200)" |
| + |
| + if [regexp $want $got] then { |
| + pass "objdump -s ($testfile, $dumpfile)" |
| + } else { |
| + fail "objdump -s ($testfile, $dumpfile)" |
| + } |
| +} |
| + |
| +test_objdump_s $testfile $testfile |
| +if { [ remote_file host exists $testarchive ] } then { |
| + test_objdump_s $testarchive bintest2.o |
| } |
| |
| # Test objdump -s on a file that contains a compressed .debug section |
| Index: git/bfd/ChangeLog |
| =================================================================== |
| --- git.orig/bfd/ChangeLog |
| +++ git/bfd/ChangeLog |
| @@ -1,3 +1,9 @@ |
| +2017-05-30 H.J. Lu <hongjiu.lu@intel.com> |
| + |
| + PR binutils/21519 |
| + * bfdio.c (bfd_get_file_size): New function. |
| + * bfd-in2.h: Regenerated. |
| + |
| 2017-06-27 Alan Modra <amodra@gmail.com> |
| |
| PR binutils/21665 |
| Index: git/binutils/ChangeLog |
| =================================================================== |
| --- git.orig/binutils/ChangeLog |
| +++ git/binutils/ChangeLog |
| @@ -1,3 +1,16 @@ |
| +2017-05-30 H.J. Lu <hongjiu.lu@intel.com> |
| + |
| + PR binutils/21519 |
| + * objdump.c (dump_relocs_in_section): Replace get_file_size |
| + with bfd_get_file_size to get archive element size. |
| + * testsuite/binutils-all/objdump.exp (test_objdump_f): New |
| + proc. |
| + (test_objdump_h): Likewise. |
| + (test_objdump_t): Likewise. |
| + (test_objdump_r): Likewise. |
| + (test_objdump_s): Likewise. |
| + Add objdump tests on archive. |
| + |
| 2017-07-01 Alan Modra <amodra@gmail.com> |
| |
| PR binutils/21665 |