On Tue, 30 Sept 2025 at 03:22, Chet Ramey <[email protected]> wrote:

> On 9/29/25 1:00 AM, Martin D Kealey wrote:
>
> > The malloc size warning is concerning, as the excessive “size” is
> > (uint64_t)(-1).
>
> It seems theoretical,


Sure, since

I guess realloc(p,0) and realloc(p,-1) are both likely to return NULL,
except the latter will set errno to ENOMEM.

The anomaly occurs in shell_getc in parse.y. It appears because new
compilers can perform constant folding between statements, and then
complain about value ranges that are more stringent that what's implied by
the parameter types:

2575:          if (shell_input_line_size > (SIZE_MAX - 256))
…
2587:              if (shell_input_line_size < SIZE_MAX)
2588:                {
2589:                  shell_input_line_size = SIZE_MAX;
2590:                  shell_input_line = xrealloc (shell_input_line,
*shell_input_line_size*);

The fallback value of SIZE_MAX appears in typemax.h:
#ifndef SIZE_MAX
#  define SIZE_MAX      ((size_t) ~(size_t)0)
#endif
which is the same as typical values from <limits.h>, and is numerically
identical to my earlier suggestion.

C11 defined a new macro RSIZE_MAX (see annex §K.3.4) as the run-time
maximum size; this is likely to be significantly smaller than SIZE_MAX,
since the latter simply expresses the maximum value that can be stored in a
size_t variable, rather than the actual maximum object size. For reasons I
don't quite follow, the committee left the definitions of malloc & realloc
as taking size_t rather than rsize_t, perhaps because they clearly signal
failure by returning NULL, so the option of undefined behaviour was not
necessary.

Attached is one possible resolution.

-Martin
diff --git a/include/typemax.h b/include/typemax.h
index e3b98f472..e9f632d10 100644
--- a/include/typemax.h
+++ b/include/typemax.h
@@ -119,6 +119,17 @@ static const unsigned long long int maxquad = ULLONG_MAX;
 #  define SIZE_MAX	((size_t) ~(size_t)0)
 #endif
 
+#ifndef RSIZE_MAX   /* C11 invention */
+#  ifndef SSIZE_MAX
+#    define SSIZE_MAX (SIZE_MAX>>1)
+#  endif
+#  if SSIZE_MAX > 65536
+#    define RSIZE_MAX ((size_t)SSIZE_MAX)
+#  else
+#    define RSIZE_MAX ((size_t)65535U)
+#  endif
+#endif
+
 #ifndef sh_imaxabs
 #  define sh_imaxabs(x)	(((x) >= 0) ? (x) : -(x))
 #endif
diff --git a/parse.y b/parse.y
index f41a6d62e..62009392d 100644
--- a/parse.y
+++ b/parse.y
@@ -47,7 +47,7 @@
 
 #include "shell.h"
 #include "execute_cmd.h"
-#include "typemax.h"		/* SIZE_MAX if needed */
+#include "typemax.h"		/* RSIZE_MAX if needed */
 #include "trap.h"
 #include "flags.h"
 #include "parser.h"
@@ -2572,21 +2572,21 @@ shell_getc (int remove_quoted_newline)
 	  /* If we can't put 256 bytes more into the buffer, allocate
 	     everything we can and fill it as full as we can. */
 	  /* XXX - we ignore rest of line using `truncating' flag */
-	  if (shell_input_line_size > (SIZE_MAX - 256))
+	  if (shell_input_line_size > (RSIZE_MAX - 256))
 	    {
 	      size_t n;
 
-	      n = SIZE_MAX - i;	/* how much more can we put into the buffer? */
+	      n = RSIZE_MAX - i;	/* how much more can we put into the buffer? */
 	      if (n <= 2)	/* we have to save 1 for the newline added below */
 		{
 		  if (truncating == 0)
-		    internal_warning(_("shell_getc: shell_input_line_size (%zu) exceeds SIZE_MAX (%lu): line truncated"), shell_input_line_size, (unsigned long)SIZE_MAX);
+		    internal_warning(_("shell_getc: shell_input_line_size (%zu) exceeds RSIZE_MAX (%jd): line truncated"), shell_input_line_size, (intmax_t)RSIZE_MAX);
 		  shell_input_line[i] = '\0';
 		  truncating = 1;
 		}
-	      if (shell_input_line_size < SIZE_MAX)
+	      if (shell_input_line_size < RSIZE_MAX)
 		{
-		  shell_input_line_size = SIZE_MAX;
+		  shell_input_line_size = RSIZE_MAX;
 		  shell_input_line = xrealloc (shell_input_line, shell_input_line_size);
 		}
 	    }
@@ -2728,7 +2728,7 @@ shell_getc (int remove_quoted_newline)
 	 not already end in an EOF character.  */
       if (shell_input_line_terminator != EOF && shell_input_line_terminator != READERR)
 	{
-	  if (shell_input_line_size + 3 < SIZE_MAX && (shell_input_line_len+3 > shell_input_line_size))
+	  if (shell_input_line_size + 3 < RSIZE_MAX && (shell_input_line_len+3 > shell_input_line_size))
 	    shell_input_line = (char *)xrealloc (shell_input_line,
 					1 + (shell_input_line_size += 2));
 

Reply via email to