From 7bed846687589e1346626e8bc9f2948340ef454b Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 15 Dec 2020 21:54:09 +1030 Subject: [PATCH] PR27071, gas bugs uncovered by fuzzing PR 27071 * config/obj-elf.c (elf_obj_symbol_clone_hook): New function. (elf_format_ops): Set symbol_clone_hook. * config/obj-elf.h (elf_obj_symbol_clone_hook): Declare. (obj_symbol_clone_hook): Define. * listing.c (buffer_line): Avoid integer overflow on paper_width set to zero. --- gas/ChangeLog | 10 ++++++++++ gas/config/obj-elf.c | 18 +++++++++++++++++- gas/config/obj-elf.h | 5 +++++ gas/listing.c | 9 ++------- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index d74fed131df..1a6c85a4699 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2020-12-15 Alan Modra + + PR 27071 + * config/obj-elf.c (elf_obj_symbol_clone_hook): New function. + (elf_format_ops): Set symbol_clone_hook. + * config/obj-elf.h (elf_obj_symbol_clone_hook): Declare. + (obj_symbol_clone_hook): Define. + * listing.c (buffer_line): Avoid integer overflow on paper_width + set to zero. + 2020-12-14 Alan Modra * testsuite/gas/elf/section27.s: Reorder .text, .data and .bss diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 5d3b1a0edc4..bee95c3f0f5 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -2102,6 +2102,22 @@ elf_obj_symbol_new_hook (symbolS *symbolP) #endif } +/* Deduplicate size expressions. We might get into trouble with + multiple freeing or use after free if we leave them pointing to the + same expressionS. */ + +void +elf_obj_symbol_clone_hook (symbolS *newsym, symbolS *orgsym ATTRIBUTE_UNUSED) +{ + struct elf_obj_sy *newelf = symbol_get_obj (newsym); + if (newelf->size) + { + expressionS *exp = XNEW (expressionS); + *exp = *newelf->size; + newelf->size = exp; + } +} + /* When setting one symbol equal to another, by default we probably want them to have the same "size", whatever it means in the current context. */ @@ -3088,6 +3104,6 @@ const struct format_ops elf_format_ops = #endif elf_obj_read_begin_hook, elf_obj_symbol_new_hook, - 0, + elf_obj_symbol_clone_hook, elf_adjust_symtab }; diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h index c714ba7a708..951109ee420 100644 --- a/gas/config/obj-elf.h +++ b/gas/config/obj-elf.h @@ -223,6 +223,11 @@ void elf_obj_symbol_new_hook (symbolS *); #define obj_symbol_new_hook elf_obj_symbol_new_hook #endif +void elf_obj_symbol_clone_hook (symbolS *, symbolS *); +#ifndef obj_symbol_clone_hook +#define obj_symbol_clone_hook elf_obj_symbol_clone_hook +#endif + void elf_copy_symbol_attributes (symbolS *, symbolS *); #ifndef OBJ_COPY_SYMBOL_ATTRIBUTES #define OBJ_COPY_SYMBOL_ATTRIBUTES(DEST, SRC) \ diff --git a/gas/listing.c b/gas/listing.c index 359dc090dc0..bf38c1ae9c2 100644 --- a/gas/listing.c +++ b/gas/listing.c @@ -508,17 +508,12 @@ buffer_line (file_info_type *file, char *line, unsigned int size) fseek (last_open_file, file->pos, SEEK_SET); } - /* Leave room for null. */ - size -= 1; - c = fgetc (last_open_file); while (c != EOF && c != '\n' && c != '\r') { - if (count < size) + if (++count < size) *p++ = c; - count++; - c = fgetc (last_open_file); } @@ -536,7 +531,7 @@ buffer_line (file_info_type *file, char *line, unsigned int size) if (c == EOF) { file->at_end = 1; - if (count + 2 < size) + if (count + 3 < size) { *p++ = '.'; *p++ = '.'; -- 2.30.2