asan: heap-buffer-overflow objdump.c:3299 in disassemble_bytes

Message ID ZgqBzM0v7HGWuCuh@squeak.grove.modra.org
State New
Headers
Series asan: heap-buffer-overflow objdump.c:3299 in disassemble_bytes |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm warning Patch is already merged
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 warning Patch is already merged

Commit Message

Alan Modra April 1, 2024, 9:43 a.m. UTC
  Fix yet another crash, this one with a fuzzed function symbol size.
The patch also corrects objdump behaviour when both --disassemble=sym
and --stop-address=value are given.  Previously --disassemble=sym
overrode --stop-address, now we take the lower of the stop-address
value and the end of function.

	* objdump.c (disassemble_section): Sanity check ELF st_size.
  

Patch

diff --git a/binutils/objdump.c b/binutils/objdump.c
index 7beb221cb2f..8293387558f 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -3923,30 +3923,26 @@  disassemble_section (bfd *abfd, asection *section, void *inf)
 		   (*rel_pp)->address - rel_offset < sym_offset)
 			  ++rel_pp;
 
+		  loop_until = next_sym;
 		  if (sym->flags & BSF_FUNCTION)
 		    {
-		      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
-			  && ((elf_symbol_type *) sym)->internal_elf_sym.st_size > 0)
-			{
-			  /* Sym is a function symbol with a size associated
-			     with it.  Turn on automatic disassembly for the
-			     next VALUE bytes.  */
-			  stop_offset = addr_offset
-			    + ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
-			  loop_until = stop_offset_reached;
-			}
-		      else
+		      loop_until = function_sym;
+
+		      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
 			{
-			  /* Otherwise we need to tell the loop heuristic to
-			     loop until the next function symbol is encountered.  */
-			  loop_until = function_sym;
+			  bfd_size_type fsize =
+			    ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+			  if (addr_offset + fsize > addr_offset
+			      && addr_offset + fsize <= stop_offset)
+			    {
+			      /* Sym is a function symbol with a valid
+				 size associated with it.  Disassemble
+				 to the end of the function.  */
+			      stop_offset = addr_offset + fsize;
+			      loop_until = stop_offset_reached;
+			    }
 			}
 		    }
-		  else
-		    {
-		      /* Otherwise loop until the next symbol is encountered.  */
-		      loop_until = next_sym;
-		    }
 		}
 
 	      free (alloc);