diff options
author | Alan Modra <amodra@gmail.com> | 2024-02-28 18:53:52 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2024-02-28 21:24:39 +1030 |
commit | 4b72a278f46245635ca03ffc8179570c07e3531a (patch) | |
tree | 7eb6aecba05182c1014f039e0f2e3d1e60717f5a /bfd/pdp11.c | |
parent | 4e0d61241012e3ae0c79603d6b6871b3407a976f (diff) | |
download | fsf-binutils-gdb-4b72a278f46245635ca03ffc8179570c07e3531a.zip fsf-binutils-gdb-4b72a278f46245635ca03ffc8179570c07e3531a.tar.gz fsf-binutils-gdb-4b72a278f46245635ca03ffc8179570c07e3531a.tar.bz2 |
PR23881, pdp11 binutils fails if too much debug data
The PR testcase overflows one of the exec header fields, e_syms (the
size of the symbol table), leading to the string table offset being
wrong. Things go downhill from there. Fixed by checking for
overflow. This happens to trigger in the ld testsuite, so xfail that
test.
PR 23881
bfd/
* libaout.h (swap_exec_header_out): Return a bool.
* aoutx.h (swap_exec_header_out): Check for overflow in exec
header.
* pdp11.c (swap_exec_header_out): Likewise.
* i386lynx.c (WRITE_HEADERS): Adjust.
ld/
* testsuite/ld-scripts/map-address.exp: xfail pdp11.
Diffstat (limited to 'bfd/pdp11.c')
-rw-r--r-- | bfd/pdp11.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/bfd/pdp11.c b/bfd/pdp11.c index 7d93904..e83a485 100644 --- a/bfd/pdp11.c +++ b/bfd/pdp11.c @@ -365,7 +365,8 @@ pdp11_aout_write_headers (bfd *abfd, struct internal_exec *execp) execp->a_drsize = 0; } - NAME (aout, swap_exec_header_out) (abfd, execp, & exec_bytes); + if (!NAME (aout, swap_exec_header_out) (abfd, execp, & exec_bytes)) + return false; if (bfd_seek (abfd, 0, SEEK_SET) != 0) return false; @@ -456,11 +457,33 @@ NAME (aout, swap_exec_header_in) (bfd *abfd, /* Swap the information in an internal exec header structure "execp" into the buffer "bytes" ready for writing to disk. */ -void +bool NAME (aout, swap_exec_header_out) (bfd *abfd, struct internal_exec *execp, struct external_exec *bytes) { + const char *err = NULL; + uint64_t val; +#define MAXVAL(x) ((UINT64_C (1) << (8 * sizeof (x) - 1) << 1) - 1) + if ((val = execp->a_text) > MAXVAL (bytes->e_text)) + err = "e_text"; + else if ((val = execp->a_data) > MAXVAL (bytes->e_data)) + err = "e_data"; + else if ((val = execp->a_bss) > MAXVAL (bytes->e_bss)) + err = "e_bss"; + else if ((val = execp->a_syms) > MAXVAL (bytes->e_syms)) + err = "e_syms"; + else if ((val = execp->a_entry) > MAXVAL (bytes->e_entry)) + err = "e_entry"; +#undef MAXVAL + if (err) + { + _bfd_error_handler (_("%pB: %#" PRIx64 " overflows header %s field"), + abfd, val, err); + bfd_set_error (bfd_error_file_too_big); + return false; + } + /* Now fill in fields in the raw data, from the fields in the exec struct. */ PUT_MAGIC (abfd, execp->a_info, bytes->e_info); PUT_WORD (abfd, execp->a_text, bytes->e_text); @@ -482,6 +505,7 @@ NAME (aout, swap_exec_header_out) (bfd *abfd, fprintf (stderr, "BFD:%s:%d: internal error\n", __FILE__, __LINE__); PUT_WORD (abfd, 0, bytes->e_flag); } + return true; } /* Make all the section for an a.out file. */ |