]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas buffer overflow with --listing-rhs-width
authorAlan Modra <amodra@gmail.com>
Fri, 27 Sep 2024 22:33:36 +0000 (08:03 +0930)
committerAlan Modra <amodra@gmail.com>
Sat, 28 Sep 2024 06:17:47 +0000 (15:47 +0930)
With listings enabled, gas keeps a small cache of source lines.  They
are stored in buffers of size LISTING_RHS_WIDTH, ie. 100.  Given
listing-rhs-width larger than 100 it is of course possible to overflow
the buffer.  Fix that by allocating as needed.  We could allocate all
buffers on the first call to print_source using listing_rhs_width, but
I chose not to do that in case some future assembly directive allows
changes to listing_rhs_width similarly to the way paper_width can
change during assembly.

gas/listing.c

index ef1798046e56a9b4d3aa535c4c2f8c6ef6b2f7b9..23f76a70ad7928aa4f1d3bf89adbb0dea92b2247 100644 (file)
@@ -1026,11 +1026,24 @@ list_symbol_table (void)
 
 typedef struct cached_line
 {
-  file_info_type * file;
-  unsigned int     line;
-  char             buffer [LISTING_RHS_WIDTH];
+  file_info_type *file;
+  unsigned int line;
+  unsigned int bufsize;
+  char *buffer;
 } cached_line;
 
+static void
+alloc_cache (cached_line *cache, unsigned int width)
+{
+  if (cache->bufsize < width)
+    {
+      cache->bufsize = width;
+      free (cache->buffer);
+      cache->buffer = xmalloc (width);
+    }
+  cache->buffer[0] = 0;
+}
+
 static void
 print_source (file_info_type *  current_file,
              list_info_type *  list,
@@ -1080,7 +1093,7 @@ print_source (file_info_type *  current_file,
 
          cache->file = current_file;
          cache->line = list->hll_line;
-         cache->buffer[0] = 0;
+         alloc_cache (cache, width);
          rebuffer_line (current_file, cache->line, cache->buffer, width);
        }
 
@@ -1101,7 +1114,7 @@ print_source (file_info_type *  current_file,
          cache = cached_lines + next_free_line;
          cache->file = current_file;
          cache->line = current_file->linenum + 1;
-         cache->buffer[0] = 0;
+         alloc_cache (cache, width);
          p = buffer_line (current_file, cache->buffer, width);
 
          /* Cache optimization:  If printing a group of lines