[binutils-gdb] gas: further limit .rept count

Alan Modra amodra@sourceware.org
Tue Feb 17 00:47:07 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=dd2a080f6e1a144779a8a9dc9c107293d1fdad77

commit dd2a080f6e1a144779a8a9dc9c107293d1fdad77
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Feb 17 09:57:52 2026 +1030

    gas: further limit .rept count
    
    gas currently limits a rept count at 0x7fffffff.  With a minimal rept
    body this requires at least 2G * 16 due to the .linefile directive
    added by buffer_and_nest.  I'm inclined to think 32G is excessive.
    
    This patch limits the total memory used by rept to 4G (2G on 32-bit
    systems).  That of course reduces allowed repeat counts by a factor of
    at least 8, and note that the file name affects the max repeat.
    
    The patch also changes the repeat count to 1 rather than 0 when
    we hit the limit, so that the body of the rept is not entirely ignored.
    
    Nested rept can still easily cause OOM of course.
    
            * read.c (do_repeat): Limit allowed repeat count based on
            total memory needed.

Diff:
---
 gas/read.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/gas/read.c b/gas/read.c
index 4f7420e4117..40804d44845 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -3200,12 +3200,9 @@ do_repeat (size_t count, const char *start, const char *end,
 {
   sb one;
   sb many;
-
-  if (count > 0x7fffffff)
-    {
-      as_bad (_("excessive count %zu for %s - ignored"), count, start);
-      count = 0;
-    }
+  size_t total, limit;
+  unsigned int line;
+  const char *file = as_where_top (&line);
 
   demand_empty_rest_of_line ();
   --input_line_pointer;
@@ -3220,6 +3217,14 @@ do_repeat (size_t count, const char *start, const char *end,
 
   sb_terminate (&one);
 
+  limit = (size_t) LONG_MAX < 0xffffffff ? (size_t) LONG_MAX : 0xffffffff;
+  if (gas_mul_overflow (count, one.len, &total) || total > limit)
+    {
+      as_bad_where (file, line,
+		    _("excessive count %zu for %s - ignored"), count, start);
+      count = 1;
+    }
+
   if (expander != NULL && !*expander && strstr (one.ptr, "\\+") != NULL)
     {
       /* The 3 here and below are arbitrary, added in an attempt to limit


More information about the Binutils-cvs mailing list