On 11/16/20 4:54 PM, Jeff Law wrote:

On 11/16/20 2:04 AM, Richard Biener via Gcc-patches wrote:
On Sun, Nov 15, 2020 at 1:46 AM Martin Sebor via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
GCC considers PTRDIFF_MAX - 1 to be the size of the largest object
so that the difference between a pointer to the byte just past its
end and the first one is no more than PTRDIFF_MAX.  This is too
liberal in LP64 on most systems because the size of the address
space is constrained to much less than that, both by the width
of the address bus for physical memory and by the practical
limitations of disk sizes for swap files.
Shouldn't this be a target hook like MAX_OFILE_ALIGNMENT then?

I think one could argue either way.  Yes, the absolutes are a function
of the underlying hardware and it can change over the lifetime of a
processor family which likey differs from MAX_OFILE_ALIGNMENT.


A PARAM gives the developer  a way to specify the limit which is more
flexible.


What I'm not really not sure of is whether is really matters in practice
for end users.

I'd like to do two things with this change: 1) make it easier
(and encourage users) to detect as early as possible more bugs
due to excessive sizes in various function calls (malloc, memcpy,
etc.), and 2) verify that GCC code uses the limit consistently
and correctly.

I envision the first would appeal to security-minded distros
and other organizations that use GCC as their system compiler.
For those, a target hook would be more convenient than a --param.
But I also expect individual projects wanting to impose stricter
limits than distros select.  For those, a --param is the only
choice (aside from individual -Wlarger-than- options(*)).

With this in mind, I think providing both a target hook and
a --param has the best chance of achieving these goals.

The attached patch does that.

Martin

[*] To enforce more realistic object size limits than PTRDIFF_MAX,
GCC users today have to set no fewer than five (or six if we count
-Wstack-usage) options: -Walloca-larger-than,
-Walloc-size-larger-than, -Wframe-larger-than, -Wlarger-than, and
-Wvla-larger-than.  The limits are all independent of one another.
I expect providing a single configurable baseline value for all
these options to use and refine to be helpful to these users.
Add new parameter max-object-size and new target hook max_object_size.

gcc/ChangeLog:

	* builtins.c (warn_string_no_nul): Print parameter when it's set.
	(maybe_warn_for_bound): Same.
	(compute_objsize_r): Use new parameter.
	* calls.c (alloc_max_size): Same.
	* doc/invoke.texi (-Walloca-larger-than): Mention new --param.
	 (-Walloc-size-larger-than): Same
	* doc/tm.texi.in (TARGET_MAX_OBJECT_SIZE): Document new hook.
	* doc/tm.texi: Same.
	* gimple-ssa-warn-alloca.c (warn_limit_specified_p): Call
	max_object_size.
	(adjusted_warn_limit): Same.
	(pass_walloca::execute): Same.
	* gimple-ssa-sprintf.c (get_string_length): Same.
	* gimple-ssa-warn-restrict.c (maybe_diag_access_bounds):
	* opt-functions.awk (function var_type_struct): Test for Host_Wide_Int.
	* params.opt (max-object-size): New parameter.
	* target.def (max_object_size): New hook.
	* targhooks.h (max_object_size): Declare function.
	* targhooks.c (max_object_size): Define function.
	* tree-ssa-strlen.c (maybe_set_strlen_range): Use new parameter.
	(get_len_or_size): Same.
	* tree.c (max_object_size): Same.

gcc/testsuite/ChangeLog:

	* c-c++-common/Warray-bounds-2.c: Adjust to new parameter value.
	* c-c++-common/Warray-bounds-3.c: Same.
	* c-c++-common/Wrestrict.c: Same.
	* g++.dg/warn/Wplacement-new-size-5.C: Same.
	* gcc.dg/Wstringop-overflow-41.c: Same.
	* gcc.dg/Wstringop-overflow-50.c: Same.
	* gcc.dg/Wstringop-overflow-54.c: Same.
	* gcc.dg/Wstringop-overflow-62.c: Same.
	* gcc.dg/Wstringop-overread-2.c: Same.
	* gcc.dg/attr-nonstring-2.c: Same.
	* gcc.dg/attr-nonstring-3.c: Same.
	* gcc.dg/attr-nonstring-4.c: Same.
	* gcc.dg/strlenopt-40.c: Same.
	* gcc.dg/Walloca-larger-than-4.c: New test.
	* gcc.dg/Wstringop-overflow-64.c: New test.
	* gcc.dg/Wvla-larger-than-5.c: New test.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index aad99da01c2..05abda5cb13 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1127,6 +1122,7 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 		 (unsigned long long) bndrng[1].to_uhwi ());
     }
 
+  bool max_exceed = false;
   const tree maxobjsize = max_object_size ();
   const wide_int maxsiz = wi::to_wide (maxobjsize);
   if (expr)
@@ -1134,7 +1130,8 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
       tree func = get_callee_fndecl (expr);
       if (bndrng)
 	{
-	  if (wi::ltu_p (maxsiz, bndrng[0]))
+	  max_exceed = wi::ltu_p (maxsiz, bndrng[0]);
+	  if (max_exceed)
 	    warned = warning_at (loc, OPT_Wstringop_overread,
 				 "%K%qD specified bound %s exceeds "
 				 "maximum object size %E",
@@ -1165,7 +1162,8 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
     {
       if (bndrng)
 	{
-	  if (wi::ltu_p (maxsiz, bndrng[0]))
+	  max_exceed = wi::ltu_p (maxsiz, bndrng[0]);
+	  if (max_exceed)
 	    warned = warning_at (loc, OPT_Wstringop_overread,
 				 "%qs specified bound %s exceeds "
 				 "maximum object size %E",
@@ -1195,8 +1193,16 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 
   if (warned)
     {
-      inform (DECL_SOURCE_LOCATION (decl),
-	      "referenced argument declared here");
+      if (max_exceed)
+	{
+	  if (param_max_object_size < HOST_WIDE_INT_MAX)
+	    inform (loc,
+		    "set by %<%s=%wu%>",
+		    "--param max-object-size", param_max_object_size);
+	}
+      else
+	inform (DECL_SOURCE_LOCATION (decl),
+		"referenced argument declared here");
       TREE_NO_WARNING (arg) = 1;
       if (expr)
 	TREE_NO_WARNING (expr) = 1;
@@ -3955,7 +3961,9 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
     {
       bool maybe = pad && pad->src.phi ();
 
-      if (tree_int_cst_lt (maxobjsize, bndrng[0]))
+      /* Set when the maximum object size has been exceeded.  */
+      const bool max_exceed = tree_int_cst_lt (maxobjsize, bndrng[0]);
+      if (max_exceed)
 	{
 	  if (bndrng[0] == bndrng[1])
 	    warned = (func
@@ -4027,7 +4035,14 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 				exp, bndrng[0], bndrng[1], size));
       if (warned)
 	{
-	  if (pad && pad->src.ref)
+	  if (max_exceed)
+	    {
+	      if (param_max_object_size < HOST_WIDE_INT_MAX)
+		inform (loc,
+			"set by %<%s=%wu%>",
+			"--param max-object-size", param_max_object_size);
+	    }
+	  else if (pad && pad->src.ref)
 	    {
 	      if (DECL_P (pad->src.ref))
 		inform (DECL_SOURCE_LOCATION (pad->src.ref),
@@ -4043,7 +4058,10 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
     }
 
   bool maybe = pad && pad->dst.phi ();
-  if (tree_int_cst_lt (maxobjsize, bndrng[0]))
+
+  /* Set when the maximum object size has been exceeded.  */
+  const bool max_exceed = tree_int_cst_lt (maxobjsize, bndrng[0]);
+  if (max_exceed)
     {
       if (bndrng[0] == bndrng[1])
 	warned = (func
@@ -4116,7 +4134,14 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 
   if (warned)
     {
-      if (pad && pad->dst.ref)
+      if (max_exceed)
+	{
+	  if (param_max_object_size < HOST_WIDE_INT_MAX)
+	    inform (loc,
+		    "set by %<%s=%wu%>",
+		    "--param max-object-size", param_max_object_size);
+	}
+      else if (pad && pad->dst.ref)
 	{
 	  if (DECL_P (pad->dst.ref))
 	    inform (DECL_SOURCE_LOCATION (pad->dst.ref),
@@ -5434,7 +5459,7 @@ compute_objsize_r (tree ptr, access_ref *pref, pointer_query *qry,
 	     length or one-element).  Set the size to the maximum minus
 	     the constant size of the type.  */
 	  pref->sizrng[0] = 0;
-	  pref->sizrng[1] = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
+	  pref->sizrng[1] = wi::to_offset (max_object_size ());
 	  if (tree recsize = TYPE_SIZE_UNIT (TREE_TYPE (ref)))
 	    if (TREE_CODE (recsize) == INTEGER_CST)
 	      pref->sizrng[1] -= wi::to_offset (recsize);
@@ -12978,6 +13003,8 @@ find_assignment_location (tree var)
       if (gimple_has_location (asgn))
 	return gimple_location (asgn);
 
+      gcc_assert (0);
+
       if (!is_gimple_assign (asgn))
 	break;
 
diff --git a/gcc/calls.c b/gcc/calls.c
index 4114bf5e5b2..22e9b6193e4 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1236,7 +1236,7 @@ alloc_max_size (void)
 
   HOST_WIDE_INT limit = warn_alloc_size_limit;
   if (limit == HOST_WIDE_INT_MAX)
-    limit = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
+    limit = tree_to_uhwi (max_object_size ());
 
   alloc_object_size_limit = build_int_cst (size_type_node, limit);
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1604f251919..0c2d0dbf0cb 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -7225,7 +7225,8 @@ Warn about calls to functions decorated with attribute @code{alloc_size}
 that attempt to allocate objects larger than the specified number of bytes,
 or where the result of the size computation in an integer type with infinite
 precision would exceed the value of @samp{PTRDIFF_MAX} on the target.
-@option{-Walloc-size-larger-than=}@samp{PTRDIFF_MAX} is enabled by default.
+@option{-Walloc-size-larger-than=}@samp{PTRDIFF_MAX} is enabled by default
+unless overridden by a smaller value of @code{--param max-object-size}.
 Warnings controlled by the option can be disabled either by specifying
 @var{byte-size} of @samp{SIZE_MAX} or more or by
 @option{-Wno-alloc-size-larger-than}.
@@ -7305,8 +7306,9 @@ expected argument to be implicitly cast into the @code{alloca} call.
 This option also warns when @code{alloca} is used in a loop.
 
 @option{-Walloca-larger-than=}@samp{PTRDIFF_MAX} is enabled by default
-but is usually only effective  when @option{-ftree-vrp} is active (default
-for @option{-O2} and above).
+unless overridden by a smaller value of @code{--param max-object-size}.
+The option is usually only effective  when @option{-ftree-vrp} is active
+(default for @option{-O2} and above).
 
 See also @option{-Wvla-larger-than=}@samp{byte-size}.
 
@@ -7799,7 +7801,8 @@ Warnings controlled by the option can be disabled either by specifying
 
 Also warn for calls to bounded functions such as @code{memchr} or
 @code{strnlen} that specify a bound greater than the largest possible
-object, which is @samp{PTRDIFF_MAX} bytes by default.  These warnings
+object, which is @samp{PTRDIFF_MAX} bytes by default unless overridden
+by a smaller value of @code{--param max-object-size}.  These warnings
 can only be disabled by @option{-Wno-larger-than}.
 
 @item -Wno-larger-than
@@ -7818,7 +7821,8 @@ even if you do not get a warning.  In addition, any space allocated
 via @code{alloca}, variable-length arrays, or related constructs
 is not included by the compiler when determining
 whether or not to issue a warning.
-@option{-Wframe-larger-than=}@samp{PTRDIFF_MAX} is enabled by default.
+@option{-Wframe-larger-than=}@samp{PTRDIFF_MAX} is enabled by default
+unless overridden by a smaller value of @code{--param max-object-size}.
 Warnings controlled by the option can be disabled either by specifying
 @var{byte-size} of @samp{SIZE_MAX} or more or by
 @option{-Wno-frame-larger-than}.
@@ -8874,9 +8878,10 @@ Note that GCC may optimize small variable-length arrays of a known
 value into plain arrays, so this warning may not get triggered for
 such arrays.
 
-@option{-Wvla-larger-than=}@samp{PTRDIFF_MAX} is enabled by default but
-is typically only effective when @option{-ftree-vrp} is active (default
-for @option{-O2} and above).
+@option{-Wvla-larger-than=}@samp{PTRDIFF_MAX} is enabled by default
+unless overridden by a smaller value of @code{--param max-object-size}.
+The option is typically only effective when @option{-ftree-vrp} is active
+(default for @option{-O2} and above).
 
 See also @option{-Walloca-larger-than=@var{byte-size}}.
 
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index f7f82911f05..746e8e73996 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1157,6 +1157,12 @@ this hook must be a power-of-two multiple of the default alignment of
 the vector element type.
 @end deftypefn
 
+@deftypefn {Target Hook} tree TARGET_MAX_OBJECT_SIZE (void)
+Return the maximum object size not affected by @code{--param max-object-size}.
+
+The default version of this function returns @code{PTRDIFF_MAX - 1}.
+@end deftypefn
+
 @defmac STACK_SLOT_ALIGNMENT (@var{type}, @var{mode}, @var{basic-align})
 If defined, a C expression to compute the alignment for stack slot.
 @var{type} is the data type, @var{mode} is the widest mode available,
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 897f2896266..67ae80c63b8 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -1082,6 +1082,8 @@ If the value of this macro has a type, it should be an unsigned type.
 
 @hook TARGET_VECTOR_ALIGNMENT
 
+@hook TARGET_MAX_OBJECT_SIZE
+
 @defmac STACK_SLOT_ALIGNMENT (@var{type}, @var{mode}, @var{basic-align})
 If defined, a C expression to compute the alignment for stack slot.
 @var{type} is the data type, @var{mode} is the widest mode available,
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index ca0572f53d3..f4820a02ef5 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -2057,7 +2057,7 @@ get_string_length (tree str, gimple *stmt, unsigned eltsize,
       return res;
     }
 
-  unsigned HOST_WIDE_INT lenmax = tree_to_uhwi (max_object_size ()) - 2;
+  unsigned HOST_WIDE_INT lenmax = param_max_object_size - 1;
   if (integer_zerop (lendata.minlen)
       && (!lendata.maxbound || lenmax <= tree_to_uhwi (lendata.maxbound))
       && lenmax <= tree_to_uhwi (lendata.maxlen))
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c
index 33824a7a091..b8e103ae933 100644
--- a/gcc/gimple-ssa-warn-alloca.c
+++ b/gcc/gimple-ssa-warn-alloca.c
@@ -142,10 +142,10 @@ warn_limit_specified_p (bool is_vla)
 /* Return the value of the argument N to -Walloca-larger-than= or
    -Wvla-larger-than= adjusted for the target data model so that
    when N == HOST_WIDE_INT_MAX, the adjusted value is set to
-   PTRDIFF_MAX on the target.  This is done to prevent warnings
-   for unknown/unbounded allocations in the "permissive mode"
-   while still diagnosing excessive and necessarily invalid
-   allocations.  */
+   MAX_OBJECT_SIZE on the target (by default PTRDIFF_MAX - 1).
+   This is done to prevent warnings for unknown/unbounded allocations
+   in the "permissive mode" while still diagnosing excessive and
+   necessarily invalid allocations.  */
 
 static unsigned HOST_WIDE_INT
 adjusted_warn_limit (bool idx)
@@ -158,7 +158,7 @@ adjusted_warn_limit (bool idx)
   if (limits[idx] != HOST_WIDE_INT_MAX)
     return limits[idx];
 
-  limits[idx] = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
+  limits[idx] = tree_to_shwi (max_object_size ());
   return limits[idx];
 }
 
@@ -294,6 +294,9 @@ pass_walloca::execute (function *fun)
 	  class alloca_type_and_limit t
 	    = alloca_call_type (ranger, stmt, is_vla);
 
+	  const unsigned HOST_WIDE_INT maxobjsize
+	    = tree_to_uhwi (max_object_size ());
+
 	  unsigned HOST_WIDE_INT adjusted_alloca_limit
 	    = adjusted_warn_limit (false);
 	  // Even if we think the alloca call is OK, make sure it's not in a
@@ -303,12 +306,13 @@ pass_walloca::execute (function *fun)
 	    {
 	      /* As in other instances, only diagnose this when the limit
 		 is less than the maximum valid object size.  */
-	      const offset_int maxobjsize
-		= wi::to_offset (max_object_size ());
-	      if (adjusted_alloca_limit < maxobjsize.to_uhwi ())
+	      if (adjusted_alloca_limit < maxobjsize)
 		t = alloca_type_and_limit (ALLOCA_IN_LOOP);
 	    }
 
+	  const unsigned HOST_WIDE_INT vla_limit
+	    = ((unsigned HOST_WIDE_INT )warn_vla_limit < maxobjsize
+	       ? warn_vla_limit : maxobjsize);
 	  enum opt_code wcode
 	    = is_vla ? OPT_Wvla_larger_than_ : OPT_Walloca_larger_than_;
 	  char buff[WIDE_INT_MAX_PRECISION / 4 + 4];
@@ -329,10 +333,17 @@ pass_walloca::execute (function *fun)
 		    && t.limit != 0)
 		  {
 		    print_decu (t.limit, buff);
-		    inform (loc, "limit is %wu bytes, but argument "
-				 "may be as large as %s",
-			    is_vla ? warn_vla_limit : adjusted_alloca_limit,
-			    buff);
+		    unsigned HOST_WIDE_INT limit
+		      = is_vla ? vla_limit : adjusted_alloca_limit;
+		    if (limit < maxobjsize)
+		      inform (loc, "limit is %wu bytes, but argument "
+			      "may be as large as %s",
+			      is_vla ? vla_limit : adjusted_alloca_limit,
+			      buff);
+		    else
+		      inform (loc, "limit set by %qs is %wu bytes, but "
+			      "argument may be as large as %s",
+			      "--param max-object-size", limit, buff);
 		  }
 	      }
 	      break;
@@ -348,9 +359,15 @@ pass_walloca::execute (function *fun)
 		    && t.limit != 0)
 		  {
 		    print_decu (t.limit, buff);
-		    inform (loc, "limit is %wu bytes, but argument is %s",
-			    is_vla ? warn_vla_limit : adjusted_alloca_limit,
-			    buff);
+		    unsigned HOST_WIDE_INT limit
+		      = is_vla ? vla_limit : adjusted_alloca_limit;
+		    if (limit < maxobjsize)
+		      inform (loc, "limit is %wu bytes, but argument is %s",
+			      limit, buff);
+		    else
+		      inform (loc, "limit set by %qs is %wu bytes, but "
+			      "argument may be as large as %s",
+			      "--param max-object-size", limit, buff);
 		  }
 	      }
 	      break;
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index 3a79e7240f9..d1461428140 100644
--- a/gcc/gimple-ssa-warn-restrict.c
+++ b/gcc/gimple-ssa-warn-restrict.c
@@ -1698,19 +1698,28 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 
       if (warn_stringop_overflow)
 	{
+	  /* TODO: Call maybe_warn_for_bound() instead.  */
+	  bool warned;
 	  if (ref.sizrange[0] == ref.sizrange[1])
-	    return warning_at (loc, OPT_Wstringop_overflow_,
-			       "%G%qD specified bound %wu "
-			       "exceeds maximum object size %wu",
-			       call, func, ref.sizrange[0].to_uhwi (),
-			       maxobjsize.to_uhwi ());
-
-	  return warning_at (loc, OPT_Wstringop_overflow_,
-			     "%G%qD specified bound between %wu and %wu "
-			     "exceeds maximum object size %wu",
-			     call, func, ref.sizrange[0].to_uhwi (),
-			     ref.sizrange[1].to_uhwi (),
-			     maxobjsize.to_uhwi ());
+	    warned = warning_at (loc, OPT_Wstringop_overflow_,
+				 "%G%qD specified bound %wu "
+				 "exceeds maximum object size %wi",
+				 call, func, ref.sizrange[0].to_uhwi (),
+				 maxobjsize.to_uhwi ());
+	  else
+	    warned = warning_at (loc, OPT_Wstringop_overflow_,
+				 "%G%qD specified bound between %wu and %wu "
+				 "exceeds maximum object size %wi",
+				 call, func, ref.sizrange[0].to_uhwi (),
+				 ref.sizrange[1].to_uhwi (),
+				 maxobjsize.to_uhwi ());
+
+	  if (warned && param_max_object_size < HOST_WIDE_INT_MAX)
+	    inform (loc,
+		    "set by %<%s=%wu%>",
+		    "--param max-object-size", param_max_object_size);
+
+	  return warned;
 	}
     }
 
diff --git a/gcc/opt-functions.awk b/gcc/opt-functions.awk
index b4952b89315..bd2ec609509 100644
--- a/gcc/opt-functions.awk
+++ b/gcc/opt-functions.awk
@@ -254,6 +254,8 @@ function var_type_struct(flags)
 		en = opt_args("Enum", flags);
 		return enum_type[en] " "
 	}
+	else if (flag_set_p("Host_Wide_Int", flags))
+		return "HOST_WIDE_INT "
 	else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) {
 		if (flag_set_p(".*Mask.*", flags)) {
 			if (host_wide_int[var_name(flags)] == "yes")
diff --git a/gcc/params.opt b/gcc/params.opt
index 5b00284c1fb..d458b7f01b1 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -561,6 +561,10 @@ The maximum number of insns in loop header duplicated by the copy loop headers p
 Common Joined UInteger Var(param_max_modulo_backtrack_attempts) Init(40) Param Optimization
 The maximum number of backtrack attempts the scheduler should make when modulo scheduling a loop.
 
+-param=max-object-size=
+Common Joined ByteSize Host_Wide_Int Var(param_max_object_size) Init(HOST_WIDE_INT_MAX) Param Optimization
+The size of the largest object.
+
 -param=max-partial-antic-length=
 Common Joined UInteger Var(param_max_partial_antic_length) Init(100) Param Optimization
 Maximum length of partial antic set when performing tree pre optimization.
diff --git a/gcc/target.def b/gcc/target.def
index ff7ad5983ac..0f3e0e9a2c4 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -6098,6 +6098,13 @@ You need not define this macro if it would always have the value zero.",
  HOST_WIDE_INT, (void),
  default_stack_clash_protection_alloca_probe_range)
 
+DEFHOOK
+(max_object_size,
+ "Return the maximum object size not affected by @code{--param max-object-size}.\n\
+\n\
+The default version of this function returns @code{PTRDIFF_MAX - 1}.",
+ tree, (void),
+ default_max_object_size)
 
 /* Functions specific to the C family of frontends.  */
 #undef HOOK_PREFIX
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 5b68a2ad7d4..8e871d060e2 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2415,4 +2415,17 @@ default_speculation_safe_value (machine_mode mode ATTRIBUTE_UNUSED,
   return result;
 }
 
+/* Return the maximum object size not affected by --param max-object-size.
+   The maximum is PTRDIFF_MAX - 1 because  the positive difference between
+   a pointer just past the last byte of the object and one to the first
+   cannot be greater than PTRDIFF_MAX.  */
+
+tree
+default_max_object_size ()
+{
+  tree ptrdiff_max = TYPE_MAX_VALUE (ptrdiff_type_node);
+  unsigned HOST_WIDE_INT max = tree_to_uhwi (ptrdiff_max) - 1;
+  return build_int_cst (sizetype, max);
+}
+
 #include "gt-targhooks.h"
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index e0a925fa2be..ef6567c4203 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -286,4 +286,6 @@ extern bool default_have_speculation_safe_value (bool);
 extern bool speculation_safe_value_not_needed (bool);
 extern rtx default_speculation_safe_value (machine_mode, rtx, rtx, rtx);
 
+extern tree default_max_object_size ();
+
 #endif /* GCC_TARGHOOKS_H */
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index b84ad2b2d55..66a7f8b5a5d 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -1852,10 +1852,9 @@ maybe_set_strlen_range (tree lhs, tree src, tree bound)
 	src = gimple_assign_rhs1 (def);
     }
 
-  /* The longest string is PTRDIFF_MAX - 1 bytes including the final
-     NUL so that the difference between a pointer to just past it and
-     one to its beginning is positive.  */
-  wide_int max = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node)) - 2;
+  /* The longest string is MAX_OBJECT_SIZE - 1 bytes including the final
+     NUL.  */
+  wide_int max = wi::shwi (param_max_object_size - 1, TYPE_PRECISION (sizetype));
 
   if (TREE_CODE (src) == ADDR_EXPR)
     {
@@ -3933,7 +3932,7 @@ get_len_or_size (gimple *stmt, tree arg, int idx,
 
       /* The longest string in this data model.  */
       const unsigned HOST_WIDE_INT lenmax
-	= tree_to_uhwi (max_object_size ()) - 2;
+	= tree_to_uhwi (max_object_size ()) - 1;
 
       if (maxbound == HOST_WIDE_INT_M1U)
 	{
diff --git a/gcc/tree.c b/gcc/tree.c
index 1ad4ad5a5f7..15d5eb82b90 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -15319,13 +15319,18 @@ const builtin_structptr_type builtin_structptr_types[6] =
   { const_fexcept_t_ptr_type_node, const_ptr_type_node, "fexcept_t" }
 };
 
-/* Return the maximum object size.  */
+/* Return the maximum object size, either set by --param max-object-size,
+   or as set by the target hook.  The default is PTRDIFF_MAX - 1.  Minus
+   1 because the positive difference between a pointer just past the last
+   byte of the object and one to the first cannot be greater than
+   PTRDIFF_MAX.  */
 
 tree
 max_object_size (void)
 {
-  /* To do: Make this a configurable parameter.  */
-  return TYPE_MAX_VALUE (ptrdiff_type_node);
+  if (param_max_object_size < HOST_WIDE_INT_MAX)
+    return build_int_cst (sizetype, param_max_object_size);
+  return targetm.max_object_size ();
 }
 
 /* A wrapper around TARGET_VERIFY_TYPE_CONTEXT that makes the silent_p
diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-2.c b/gcc/testsuite/c-c++-common/Warray-bounds-2.c
index 7400a29d4be..9aaada3cf3b 100644
--- a/gcc/testsuite/c-c++-common/Warray-bounds-2.c
+++ b/gcc/testsuite/c-c++-common/Warray-bounds-2.c
@@ -176,14 +176,14 @@ wrap_strncpy_src_diff_max_m1 (char *d, const char *s, ptrdiff_t i, size_t n)
 {
   /* Unlike in the similar call to memcpy(), there is no pointer
      overflow here because the size N is not added to the source
-     offset MAX - 1 (only 1 is for the access to its first element,
+     offset MAX - 2 (only 1 is for the access to its first element,
      which is tested below).  */
   strncpy (d, s + i, n);
 }
 
 void call_strncpy_src_diff_max_m1 (char *d, const char *s, size_t n)
 {
-  wrap_strncpy_src_diff_max_m1 (d, s, MAX - 1, 3);
+  wrap_strncpy_src_diff_max_m1 (d, s, MAX - 2, 3);
 }
 
 static void
diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-3.c b/gcc/testsuite/c-c++-common/Warray-bounds-3.c
index d9b3864203f..682769a5465 100644
--- a/gcc/testsuite/c-c++-common/Warray-bounds-3.c
+++ b/gcc/testsuite/c-c++-common/Warray-bounds-3.c
@@ -25,6 +25,7 @@ extern char* strncpy (char* restrict, const char* restrict, size_t);
 #endif
 
 void sink (void*, ...);
+#define sink(p, ...) sink (0, (__INTPTR_TYPE__)p)
 
 #define CAT(x, y)      x ## y
 #define CONCAT(x, y)   CAT (x, y)
@@ -157,7 +158,7 @@ void test_memcpy_overflow (char *d, const char *s, size_t n)
   /* Verify that offset overflow involving an array of unknown size
      but known access size is detected.  This works except with small
      sizes that are powers of 2 due to bug .  */
-  T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 1);
+  T (char, 1, arr + SR (DIFF_MAX - 2, DIFF_MAX), s, 1);
   T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 2);  /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 2 accessing array " "bug " { xfail non_strict_align } } */
   T (char, 1, arr + SR (DIFF_MAX - 2, DIFF_MAX), s, 3);  /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 3 accessing array " "memcpy" } */
   T (char, 1, arr + SR (DIFF_MAX - 4, DIFF_MAX), s, 5);  /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 5 accessing array " "memcpy" } */
diff --git a/gcc/testsuite/c-c++-common/Wrestrict.c b/gcc/testsuite/c-c++-common/Wrestrict.c
index 9eb02bdbfcb..98e1f1e2ef1 100644
--- a/gcc/testsuite/c-c++-common/Wrestrict.c
+++ b/gcc/testsuite/c-c++-common/Wrestrict.c
@@ -314,11 +314,11 @@ void test_memcpy_anti_range (char *d, const char *s)
   T (d, d + SAR (0, 3), 1);
   T (d, d + SAR (0, 3), 2);
   T (d, d + SAR (0, 3), 3);
-  T (d, d + SAR (0, 3), DIFF_MAX - 2);   /* { dg-warning "overlaps \[0-9\]+ bytes at offset 2" "memcpy" } */
-  T (d, d + SAR (0, 3), DIFF_MAX - 1);   /* { dg-warning "overlaps \[0-9\]+ bytes at offset 1" "memcpy" } */
-  T (d, d + SAR (0, 3), DIFF_MAX);       /* { dg-warning "overlaps \[0-9\]+ bytes at offset 0" "memcpy" } */
+  T (d, d + SAR (0, 3), DIFF_MAX - 3);   /* { dg-warning "overlaps \\d+ bytes at offset 2 " "memcpy" } */
+  T (d, d + SAR (0, 3), DIFF_MAX - 2);   /* { dg-warning "overlaps \\d+ bytes at offset 1" "memcpy" } */
+  T (d, d + SAR (0, 3), DIFF_MAX - 1);   /* { dg-warning "overlaps \[0-9\]+ bytes at offset 0" "memcpy" } */
 
-  T (d, d + SAR (0, 3), UR (DIFF_MAX - 2, DIFF_MAX));               /* { dg-warning "accessing \[0-9\]+ or more bytes at offsets 0 and \\\[-?\[0-9\]+, -?\[0-9\]+] overlaps \[0-9\]+ bytes at offset 2" "memcpy" } */
+  T (d, d + SAR (0, 3), UR (DIFF_MAX - 2, DIFF_MAX));               /* { dg-warning "accessing \[0-9\]+ or more bytes at offsets 0 and \\\[-?\[0-9\]+, -?\[0-9\]+] overlaps \[0-9\]+ bytes at offset 1" "memcpy" } */
 
   /* Verify that a size in an anti-range ~[1, N] where N >= PTRDIFF_MAX - 2
      doesn't trigger a warning.
@@ -327,7 +327,7 @@ void test_memcpy_anti_range (char *d, const char *s)
      ptrdiff_t.  Since such a large object cannot exist, so the size of
      the region must be zero.  */
   T (d, s, UAR (1, DIFF_MAX / 2 - 1));
-  T (d, s, UAR (1, DIFF_MAX - 1));
+  T (d, s, UAR (1, DIFF_MAX - 2));
   T (d, s, UAR (1, DIFF_MAX));
   T (d, s, UAR (1, SIZE_MAX - 1));
   T (d, s, UAR (1, SIZE_MAX));
@@ -358,37 +358,37 @@ void test_memcpy_range_exceed (char *d, const char *s)
      whose aggregate size would exceed DIFF_MAX if it were to not
      overlap.  */
   T (d, s, DIFF_MAX / 2);
-  T (d, s, DIFF_MAX / 2 + 1);   /* { dg-warning "overlaps 1 byte" "memcpy" } */
-  T (d, s, DIFF_MAX / 2 + 2);   /* { dg-warning "overlaps 3 bytes" "memcpy" } */
-  T (d, s, DIFF_MAX / 2 + 3);   /* { dg-warning "overlaps 5 bytes" "memcpy" } */
+  T (d, s, DIFF_MAX / 2 + 1);   /* { dg-warning "overlaps 2 bytes" "memcpy" } */
+  T (d, s, DIFF_MAX / 2 + 2);   /* { dg-warning "overlaps 4 bytes" "memcpy" } */
+  T (d, s, DIFF_MAX / 2 + 3);   /* { dg-warning "overlaps 6 bytes" "memcpy" } */
 
   i = SR (DIFF_MAX - 2, DIFF_MAX);
 
   /* Verify a warning for an out-of-bounds offset range and constant
      size addition.  */
-  T (d, d + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
-  T (d + i, d, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 0 overlaps 1 byte" "memcpy" } */
+  T (d, d + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[\[0-9\]+, \[0-9\]+] overlaps 2 bytes" "memcpy" } */
+  T (d + i, d, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 0 overlaps 2 bytes" "memcpy" } */
 
-  T (d + 1, d + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 1 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
-  T (d + i, d + 1, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 1 overlaps 1 byte" "memcpy" } */
+  T (d + 1, d + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 1 and \\\[\[0-9\]+, \[0-9\]+] overlaps 2 bytes" "memcpy" } */
+  T (d + i, d + 1, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 1 overlaps 2 bytes" "memcpy" } */
 
   /* Verify that the warnings above are independent of whether the source
      and destination are known to be based on the same object.  */
-  T (d, s + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
-  T (d + i, s, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 0 overlaps 1 byte" "memcpy" } */
+  T (d, s + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[\[0-9\]+, \[0-9\]+] overlaps 2 bytes" "memcpy" } */
+  T (d + i, s, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 0 overlaps 2 bytes" "memcpy" } */
 
-  T (d + 1, s + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 1 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
-  T (d + i, s + 1, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 1 overlaps 1 byte" "memcpy" } */
+  T (d + 1, s + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 1 and \\\[\[0-9\]+, \[0-9\]+] overlaps 2 bytes" "memcpy" } */
+  T (d + i, s + 1, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 1 overlaps 2 bytes" "memcpy" } */
 
 #if __SIZEOF_SIZE_T__ == 8
   /* Verfiy the offset and size computation is correct.  The overlap
      offset mentioned in the warning plus sthe size of the access must
      not exceed DIFF_MAX.  */
-  T (d, d + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[9223372036854775805, 9223372036854775807] overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
-  T (d + i, d, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[9223372036854775805, 9223372036854775807] and 0 overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
+  T (d, d + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[9223372036854775805, 9223372036854775807] overlaps 4 bytes at offset 9223372036854775801" "LP64" { target lp64 } } */
+  T (d + i, d, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[9223372036854775805, 9223372036854775807] and 0 overlaps 4 bytes at offset 9223372036854775801" "LP64" { target lp64 } } */
 
-  T (d, s + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[9223372036854775805, 9223372036854775807] overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
-  T (d + i, s, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[9223372036854775805, 9223372036854775807] and 0 overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
+  T (d, s + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[9223372036854775805, 9223372036854775807] overlaps 4 bytes at offset 9223372036854775801" "LP64" { target lp64 } } */
+  T (d + i, s, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[9223372036854775805, 9223372036854775807] and 0 overlaps 4 bytes at offset 9223372036854775801" "LP64" { target lp64 } } */
 #elif __SIZEOF_SIZE_T__ == 4
   T (d, d + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[2147483645, 2147483647] overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32 } } */
   T (d + i, d, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[2147483645, 2147483647] and 0 overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32 } } */
@@ -408,7 +408,7 @@ void test_memcpy_range_exceed (char *d, const char *s)
   n = UR (4, SIZE_MAX - 1);
   T (d + i, d + j, n);
 
-  j = SR (DIFF_MAX - 8, DIFF_MAX - 1);
+  j = SR (DIFF_MAX - 9, DIFF_MAX - 1);
   T (d + i, d + j, n);
 
   j = SR (DIFF_MAX - 7, DIFF_MAX - 1);
@@ -417,20 +417,17 @@ void test_memcpy_range_exceed (char *d, const char *s)
   j = SR (DIFF_MAX - 6, DIFF_MAX - 1);
   T (d + i, d + j, n);   /* { dg-warning "accessing 4( or more)? bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps" "memcpy" } */
 
-  n = UR (3, DIFF_MAX);
+  n = UR (2, DIFF_MAX);
   T (d + i, d + j, n);
 
-  j = SR (DIFF_MAX - 6, DIFF_MAX - 1);
+  j = SR (DIFF_MAX - 7, DIFF_MAX - 1);
   T (d + i, d + j, n);
 
-  j = SR (DIFF_MAX - 5, DIFF_MAX - 1);
-  T (d + i, d + j, n);   /* { dg-warning "accessing 3 or more bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 or more bytes" "memcpy" } */
-
-  j = SR (DIFF_MAX - 4, DIFF_MAX - 1);
-  T (d + i, d + j, n);   /* { dg-warning "accessing 3 or more bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 or more bytes" "memcpy" } */
+  j = SR (DIFF_MAX - 3, DIFF_MAX - 1);
+  T (d + i, d + j, n);
 
   j = SR (DIFF_MAX - 2, DIFF_MAX - 1);
-  T (d + i, d + j, n);   /* { dg-warning "accessing 3 or more bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 or more bytes" "memcpy" } */
+  T (d + i, d + j, n);   /* { dg-warning "accessing 2 or more bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 or more bytes" "memcpy" } */
 }
 
 /* Exercise memcpy with destination and source of unknown size.  */
diff --git a/gcc/testsuite/g++.dg/warn/Wplacement-new-size-5.C b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-5.C
index 4afc7e503ab..7786419e3ee 100644
--- a/gcc/testsuite/g++.dg/warn/Wplacement-new-size-5.C
+++ b/gcc/testsuite/g++.dg/warn/Wplacement-new-size-5.C
@@ -236,7 +236,8 @@ void test_vla (unsigned n)
   new (&cvla[9]) A;
   new (&cvla[n - 1]) A;
   new (cvla + n - 1) A;
-  new (&cvla[DIFF_MAX - 1]) A;
+  new (&cvla[DIFF_MAX - 2]) A;
+  new (&cvla[DIFF_MAX - 1]) A;      // { dg-warning "\\\[-Wplacement-new"}
   new (&cvla[DIFF_MAX]) A;          // { dg-warning "\\\[-Wplacement-new" }
   new (cvla + DIFF_MAX) A;          // { dg-warning "\\\[-Wplacement-new" }
   new (&cvla[SIZE_MAX]) A;          // { dg-warning "\\\[-Wplacement-new" }
diff --git a/gcc/testsuite/gcc.dg/Walloca-larger-than-4.c b/gcc/testsuite/gcc.dg/Walloca-larger-than-4.c
new file mode 100644
index 00000000000..43f334eed90
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Walloca-larger-than-4.c
@@ -0,0 +1,21 @@
+/* Verify that --param max-object-size is recognized and respected.
+   { dg-do compile }
+   { dg-options "-O -Wall --param max-object-size=1234" }
+   { dg-require-effective-target alloca } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* alloca (size_t);
+
+void sink (void*);
+
+void test_alloca (void)
+{
+  void *p = alloca (1234);
+  sink (p);
+
+  p = alloca (1235);
+  // { dg-warning "argument to 'alloca' is too large" "" { target *-*-* } .-1 }
+  // { dg-message "limit set by '--param max-object-size' is 1234" "note" { target *-*-* } .-2 }
+  sink (p);
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-41.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-41.c
index 9b2d2cbc501..d0790c22abb 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-41.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-41.c
@@ -16,10 +16,10 @@ void sink (void*);
 
 void char_array_cst_off_cst_size (void)
 {
-  extern char caxcc[];                  // { dg-message "at offset \\d+ into destination object 'caxcc'" }
+  extern char caxcc[];                  // { dg-message "at offset \\d+ into destination object 'caxcc'" "note" }
 
   char *p = caxcc;
-  size_t idx = DIFF_MAX - 3;
+  size_t idx = DIFF_MAX - 4;
 
   memset (p + idx, 0, 3);
   sink (p);
@@ -43,29 +43,29 @@ void char_array_var_off_cst_size (size_t idx)
      bound of DIFF_MAX.  There's not point in also mentioning the latter
      (it wouldn't make the note any more meaningful) so verify it only
      mentions the lower bound.  */
-  extern char caxvc[];                  // { dg-message "at offset \\d+ into destination object 'caxvc'" "note" }
+  extern char caxvc[];                  // { dg-message "at offset \\\[\\d+, \\d+] into destination object 'caxvc'" "note" }
 
   char *p = caxvc;
 
-  if (idx < DIFF_MAX - 3)
-    idx = DIFF_MAX - 3;
+  if (idx < DIFF_MAX - 4)
+    idx = DIFF_MAX - 4;
 
   memset (p + idx, 0, 3);
   sink (p);
 
-  memset (p + idx, 0, 5);               // { dg-warning "writing 5 bytes into a region of size 3" }
+  memset (p + idx, 0, 4);               // { dg-warning "writing 4 bytes into a region of size 3" }
   sink (p);
 }
 
 
 void char_array_var_off_var_size (size_t idx, size_t n)
 {
-  extern char caxvv[];                  // { dg-message "at offset \\d+ into destination object 'caxvv'" "note" }
+  extern char caxvv[];                  // { dg-message "at offset \\\[\\d+, \\d+] into destination object 'caxvv'" "note" }
 
   char *p = caxvv;
 
-  if (idx < DIFF_MAX - 3)
-    idx = DIFF_MAX - 3;
+  if (idx < DIFF_MAX - 4)
+    idx = DIFF_MAX - 4;
 
   if (n < 3 || 7 < n)
     n = 3;
@@ -81,10 +81,10 @@ void char_array_var_off_var_size (size_t idx, size_t n)
 
 void alloc_array_var_off_cst_size (size_t n, size_t idx)
 {
-  char *p = malloc (n);                 // { dg-message "at offset \\d+ into destination object" "note" }
+  char *p = malloc (n);                 // { dg-message "at offset \\\[\\d+, \\d+] into destination object" "note" }
 
-  if (idx < DIFF_MAX - 3)
-    idx = DIFF_MAX - 3;
+  if (idx < DIFF_MAX - 4)
+    idx = DIFF_MAX - 4;
 
   memset (p + idx, 0, 3);
   sink (p);
@@ -101,10 +101,10 @@ void int_array_cst_off_cst_size (void)
   int *p = iaxc;
   size_t idx = DIFF_MAX / sizeof *iaxc;
 
-  memset (p + idx, 0, 3);
+  memset (p + idx, 0, 2);
   sink (p);
 
-  memset (p + idx, 0, 5);               // { dg-warning "writing 5 bytes into a region of size 3" }
+  memset (p + idx, 0, 3);               // { dg-warning "writing 3 bytes into a region of size 2" }
   sink (p);
 }
 
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-50.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-50.c
index 7df58e5209e..a784b65bee5 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-50.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-50.c
@@ -17,7 +17,7 @@ char* fcall (void);
 void char_ptr_cst_off_cst_size (char *p)
                                         // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'p'" "note" { target *-*-* } .-1 }
 {
-  size_t idx = DIFF_MAX - 3;
+  size_t idx = DIFF_MAX - 4;
 
   memset (p + idx, 0, 3);
   sink (p);
@@ -43,8 +43,8 @@ void char_ptr_var_difoff_cst_size (ptrdiff_t idx)
      mentions the lower bound.
      { dg-message "at offset \\d+ into destination object of size \\\[0, \\d+] (allocated|returned) by 'fcall'" "note" { target *-*-* } .-5 } */
 
-  if (idx < DIFF_MAX - 3)
-    idx = DIFF_MAX - 3;
+  if (idx < DIFF_MAX - 4)
+    idx = DIFF_MAX - 4;
 
   memset (p + idx, 0, 3);
   sink (p);
@@ -60,8 +60,8 @@ void char_ptr_var_szoff_cst_size (size_t idx)
 
   char *p = gptr;
 
-  if (idx < DIFF_MAX - 3)
-    idx = DIFF_MAX - 3;
+  if (idx < DIFF_MAX - 4)
+    idx = DIFF_MAX - 4;
 
   memset (p + idx, 0, 3);
   sink (p);
@@ -78,8 +78,8 @@ void char_ptr_var_szoff_cst_size (size_t idx)
 void char_ptr_var_difoff_var_size (char *p, ptrdiff_t idx, size_t n)
                                         // { dg-message "at offset \\d+ into destination object 'p'" "note" { target *-*-* } .-1 }
 {
-  if (idx < DIFF_MAX - 3)
-    idx = DIFF_MAX - 3;
+  if (idx < DIFF_MAX - 4)
+    idx = DIFF_MAX - 4;
 
   if (n < 3 || 7 < n)
     n = 3;
@@ -95,8 +95,8 @@ void char_ptr_var_difoff_var_size (char *p, ptrdiff_t idx, size_t n)
 void char_ptr_var_szoff_var_size (char *p, size_t idx, size_t n)
                                         // { dg-message "at offset \\\[\[1-9\]\[0-9\]+, \[1-9\]\[0-9\]+] into destination object 'p'" "note" { xfail *-*-* } .-1 }
 {
-  if (idx < DIFF_MAX - 3)
-    idx = DIFF_MAX - 3;
+  if (idx < DIFF_MAX - 4)
+    idx = DIFF_MAX - 4;
 
   if (n < 3 || 7 < n)
     n = 3;
@@ -114,12 +114,15 @@ void char_ptr_var_szoff_var_size (char *p, size_t idx, size_t n)
 
 
 void int_ptr_cst_off_cst_size (int *p)
-                                        // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'p'" "note" { target *-*-* } .-1 }
+                                        // { dg-message "at offset \\d+ into destination object 'p'" "note" { target *-*-* } .-1 }
 {
   size_t idx = DIFF_MAX / sizeof *p;
 
-  memset (p + idx, 0, 3);
+  memset (p + idx, 0, 1);
   sink (p);
 
-  memset (p + idx, 0, 5);               // { dg-warning "writing 5 bytes into a region of size 3" }
+  memset (p + idx, 0, 2);
+  sink (p);
+
+  memset (p + idx, 0, 3);               // { dg-warning "writing 3 bytes into a region of size 2" }
 }
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c
index f5929c9e7d6..4bb3b06387f 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-54.c
@@ -18,7 +18,7 @@ void char_flexarray_cst_off_cst_size (void)
     caxcc;                              // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'caxcc'" "note" }
 
   char *p = caxcc.a;
-  size_t idx = DIFF_MAX - 4;
+  size_t idx = DIFF_MAX - 5;
 
   memset (p + idx, 0, 3);
   sink (p);
@@ -42,8 +42,8 @@ void char_flexarray_var_off_cst_size (ptrdiff_t idx)
 
   char *p = caxvc.a;
 
-  if (idx < DIFF_MAX - 4)
-    idx = DIFF_MAX - 4;
+  if (idx < DIFF_MAX - 5)
+    idx = DIFF_MAX - 5;
 
   memset (p + idx, 0, 3);
   sink (p);
@@ -59,8 +59,8 @@ void char_flexarray_var_off_var_size (size_t n, ptrdiff_t idx)
 
   char *p = caxvv.a;
 
-  if (idx < DIFF_MAX - 4)
-    idx = DIFF_MAX - 4;
+  if (idx < DIFF_MAX - 5)
+    idx = DIFF_MAX - 5;
 
   if (n < 3 || 7 < n)
     n = 3;
@@ -76,10 +76,10 @@ void char_flexarray_var_off_var_size (size_t n, ptrdiff_t idx)
 void alloc_array_var_off_cst_size (size_t n, ptrdiff_t idx)
 {
   struct { char n, a[]; }
-    *p = __builtin_malloc (n);          // { dg-message "at offset \\d+ into destination object" "note" }
+    *p = __builtin_malloc (n);          // { dg-message "at offset \\\[\\d+, \\d+] into destination object" "note" }
 
-  if (idx < DIFF_MAX - 4)
-    idx = DIFF_MAX - 4;
+  if (idx < DIFF_MAX - 5)
+    idx = DIFF_MAX - 5;
 
   memset (p->a + idx, 0, 3);
   sink (p);
@@ -91,13 +91,14 @@ void alloc_array_var_off_cst_size (size_t n, ptrdiff_t idx)
 void int_array_cst_off_cst_size (void)
 {
   extern struct { int n, a[]; }
-    iaxc;                               // { dg-message "at offset \[1-9\]\[0-9\]+ into destination object 'iaxc'" "note" }
+    iaxc;                               // { dg-message "at offset \\d+ into destination object 'iaxc'" "note" }
 
   int *p = iaxc.a;
   size_t idx = DIFF_MAX / sizeof *p - 1;
 
-  memset (p + idx, 0, 3);
+  memset (p + idx, 0, 2);
   sink (p);
 
-  memset (p + idx, 0, 5);               // { dg-warning "writing 5 bytes into a region of size 3" }
+  memset (p + idx, 0, 3);               // { dg-warning "writing 3 bytes into a region of size 2" }
+  sink (p);
 }
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c
index 318d9bd1f94..ff2ab8d832f 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-62.c
@@ -39,9 +39,9 @@ void test_min (void)
     memset (q, 0, INT_MAX);
     // { dg-warning "writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 }
     memset (q, 0, DIFF_MAX - 2);
-    memset (q, 0, DIFF_MAX);
-    // { dg-warning "writing 2147483647 bytes into a region of size 2147483646" "ilp32" { target ilp32 } .-1 }
-    // { dg-warning "writing 9223372036854775807 bytes into a region of size 9223372036854775806" "lp64" { target lp64 } .-2 }
+    memset (q, 0, DIFF_MAX - 1);
+    // { dg-warning "writing 2147483646 bytes into a region of size 2147483645" "ilp32" { target ilp32 } .-1 }
+    // { dg-warning "writing 9223372036854775806 bytes into a region of size 9223372036854775805" "lp64" { target lp64 } .-2 }
   }
 
   {
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-64.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-64.c
new file mode 100644
index 00000000000..074fc2a8397
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-64.c
@@ -0,0 +1,19 @@
+/* Verify that --param max-object-size is recognized and respected.
+   { dg-do compile }
+   { dg-options "-O -Wall --param max-object-size=123" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* memset (void*, int, size_t);
+
+void sink (void*);
+
+void test_memset (void *p)
+{
+  memset (p, 0, 123);
+  memset (p, 0, 124);
+  // { dg-warning "specified bound 124 exceeds maximum object size 123 " "" { target *-*-* } .-1 }
+  // { dg-message "set by '--param max-object-size=123'" "note" { target *-*-* } .-2 }
+  sink (p);
+  memset (p, 0, 125);   // { dg-warning "\\\[-Wstringop-overflow" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overread-2.c b/gcc/testsuite/gcc.dg/Wstringop-overread-2.c
index 16dc06d968b..8a42f6680b1 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overread-2.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overread-2.c
@@ -25,11 +25,15 @@ void sink (int, ...);
 
 NOIPA void test_memchr (const void *p, int x)
 {
+  /* The size of the largest possible object cannot exceed PTRDIFF_MAX - 1
+     so that the difference between a pointer just past its last byte and
+     the first byte doesn't is at most PTRDIFF_MAX.  */
   size_t dmax = PTRDIFF_MAX;
   size_t smax = SIZE_MAX;
 
-  T (memchr (p, x, dmax));
+  T (memchr (p, x, dmax - 1));
 
+  T (memchr (p, x, dmax));         // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
   T (memchr (p, x, dmax + 1));     // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
   T (memchr (p, x, dmax * 2));     // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
   T (memchr (p, x, smax));         // { dg-warning "\\\[-Wstringop-overread" }
@@ -41,8 +45,9 @@ NOIPA void test_memcmp (const void *p, const void *q)
   size_t dmax = PTRDIFF_MAX;
   size_t smax = SIZE_MAX;
 
-  T (memcmp (p, q, dmax));
+  T (memcmp (p, q, dmax - 1));
 
+  T (memcmp (p, q, dmax));         // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
   T (memcmp (p, q, dmax + 1));     // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
   T (memcmp (p, q, dmax * 2));     // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
   T (memcmp (p, q, smax));         // { dg-warning "\\\[-Wstringop-overread" }
@@ -54,9 +59,10 @@ NOIPA void test_memcpy (void *p, const void *q)
   size_t dmax = PTRDIFF_MAX;
   size_t smax = SIZE_MAX;
 
-  T (memcpy (p, q, dmax));
+  T (memcpy (p, q, dmax - 1));
 
-  T (memcpy (p, q, dmax + 1));    // -Wstringop-overflow disabled
+  T (memcpy (p, q, dmax));        // -Wstringop-overflow disabled
+  T (memcpy (p, q, dmax + 1));    // ditto
   T (memcpy (p, q, dmax * 2));    // ditto
   T (memcpy (p, q, smax));        // ditto
 }
@@ -67,8 +73,9 @@ NOIPA void test_strncmp (const char *p, const char *q)
   size_t dmax = PTRDIFF_MAX;
   size_t smax = SIZE_MAX;
 
-  T (strncmp (p, q, dmax));
+  T (strncmp (p, q, dmax - 1));
 
+  T (strncmp (p, q, dmax));       // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" "strncmp" }
   T (strncmp (p, q, dmax + 1));   // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" "strncmp" }
   T (strncmp (p, q, dmax * 2));   // { dg-warning "\\\[-Wstringop-overread" "strncmp" }
   T (strncmp (p, q, smax));       // { dg-warning "\\\[-Wstringop-overread" "strncmp" }
@@ -79,8 +86,9 @@ NOIPA void test_strncat (char *p, const char *q)
   size_t dmax = PTRDIFF_MAX;
   size_t smax = SIZE_MAX;
 
-  T (strncat (p, q, dmax));
+  T (strncat (p, q, dmax - 1));
 
+  T (strncat (p, q, dmax));       // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
   T (strncat (p, q, dmax + 1));   // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
   T (strncat (p, q, dmax * 2));   // { dg-warning "\\\[-Wstringop-overread" }
   T (strncat (p, q, smax));       // { dg-warning "\\\[-Wstringop-overread" }
@@ -98,7 +106,8 @@ NOIPA void test_strncpy (char *p, const char *q)
 
   T (strncpy (p, q, dmax));
 
-  T (strncpy (p, q, dmax + 1));    // -Wstringop-overflow disabled
+  T (strncpy (p, q, dmax));        // -Wstringop-overflow disabled
+  T (strncpy (p, q, dmax + 1));    // ditto
   T (strncpy (p, q, dmax * 2));    // ditto
   T (strncpy (p, q, smax));        // ditto
 #endif
@@ -109,8 +118,9 @@ NOIPA void test_strnlen (const char *p)
   size_t dmax = PTRDIFF_MAX;
   size_t smax = SIZE_MAX;
 
-  T (strnlen (p, dmax));
+  T (strnlen (p, dmax - 1));
 
+  T (strnlen (p, dmax));          // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
   T (strnlen (p, dmax + 1));      // { dg-warning "specified bound \[0-9\]+ exceeds maximum object size" }
   T (strnlen (p, dmax * 2));      // { dg-warning "\\\[-Wstringop-overread" }
   T (strnlen (p, smax));          // { dg-warning "\\\[-Wstringop-overread" }
diff --git a/gcc/testsuite/gcc.dg/Wvla-larger-than-5.c b/gcc/testsuite/gcc.dg/Wvla-larger-than-5.c
new file mode 100644
index 00000000000..4abc3719e88
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wvla-larger-than-5.c
@@ -0,0 +1,23 @@
+/* Verify that --param max-object-size is recognized and respected.
+   { dg-do compile }
+   { dg-options "-O -Wall --param max-object-size=1234" }
+   { dg-require-effective-target alloca } */
+
+void sink (void*);
+
+void test_vla (void)
+{
+  int n = 1234;
+  {
+    char a[n];
+    sink (a);
+  }
+
+  ++n;
+  {
+    char a[n];
+    // { dg-warning "argument to variable-length array is too large" "" { target *-*-* } .-1 }
+    // { dg-message "limit set by '--param max-object-size' is 1234" "note" { target *-*-* } .-2 }
+    sink (a);
+  }
+}
diff --git a/gcc/testsuite/gcc.dg/attr-nonstring-2.c b/gcc/testsuite/gcc.dg/attr-nonstring-2.c
index ba4757d673f..20e3fa7772d 100644
--- a/gcc/testsuite/gcc.dg/attr-nonstring-2.c
+++ b/gcc/testsuite/gcc.dg/attr-nonstring-2.c
@@ -27,7 +27,8 @@ void test_strnlen_array_cst (void)
   T (strnlen (ns3, 2));
   T (strnlen (ns3, 3));
   T (strnlen (ns3, 4));             /* { dg-warning "specified bound 4 exceeds source size 3" } */
-  T (strnlen (ns3, DIFF_MAX));      /* { dg-warning "specified bound \[0-9\]+ exceeds source size" } */
+  T (strnlen (ns3, DIFF_MAX - 1));  /* { dg-warning "specified bound \[0-9\]+ exceeds source size" } */
+  T (strnlen (ns3, DIFF_MAX));      /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
   T (strnlen (ns3, SIZE_MAX));      /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
 
   NONSTRING char ns5[5];
@@ -38,7 +39,8 @@ void test_strnlen_array_cst (void)
   T (strnlen (ns5, 2));
   T (strnlen (ns5, 3));
   T (strnlen (ns5, 6));             /* { dg-warning "specified bound 6 exceeds source size 5" } */
-  T (strnlen (ns5, DIFF_MAX));      /* { dg-warning "specified bound \[0-9\]+ exceeds source size 5" } */
+  T (strnlen (ns5, DIFF_MAX - 1));  /* { dg-warning "specified bound \[0-9\]+ exceeds source size 5" } */
+  T (strnlen (ns5, DIFF_MAX));      /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
   T (strnlen (ns5, SIZE_MAX));      /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
 }
 
@@ -53,7 +55,8 @@ void test_strnlen_array_range (void)
   T (strnlen (ns3, UR (3, 4)));
   T (strnlen (ns3, UR (3, DIFF_MAX)));
   T (strnlen (ns3, UR (4, 5)));     /* { dg-warning "specified bound \\\[4, 5] exceeds source size 3" } */
-  T (strnlen (ns3, UR (DIFF_MAX, SIZE_MAX)));  /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds source size 3 " } */
+  T (strnlen (ns3, UR (DIFF_MAX - 1, SIZE_MAX)));  /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds source size 3 " } */
+  T (strnlen (ns3, UR (DIFF_MAX, SIZE_MAX)));  /* { dg-warning "specified bound \\\[\[0-9\]+, \[0-9\]+] exceeds maximum object size " } */
 }
 
 
@@ -98,7 +101,7 @@ void test_strnlen_string_cst (void)
   T (/* [] */, "1", 2, DIFF_MAX);
   T (/* [] */, "1", 2, SIZE_MAX);
 
-  size_t n = DIFF_MAX;
+  size_t n = DIFF_MAX - 1;
   T (/* [] */, "123", 3, n);
   T (/* [] */, "123", 3, n + 1);    /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size " } */
   n = SIZE_MAX;
diff --git a/gcc/testsuite/gcc.dg/attr-nonstring-3.c b/gcc/testsuite/gcc.dg/attr-nonstring-3.c
index 34f31fb6aa7..3eb80238b60 100644
--- a/gcc/testsuite/gcc.dg/attr-nonstring-3.c
+++ b/gcc/testsuite/gcc.dg/attr-nonstring-3.c
@@ -32,7 +32,10 @@ void sink (int);
 
 void strncmp_cst (void)
 {
-  size_t n = DIFF_MAX;
+  /* The largest object is DIFF_MAX - 1 bytes so that the difference
+     between a pointer just past the last byte and the first is no
+     more than DIFF_MAX.  */
+  size_t n = DIFF_MAX - 1;
 
   T (STR, /* [] */, STR, /* [] */, n);
   T (STR, /* [] */, STR, /* [] */, n + 1);    /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
@@ -84,7 +87,7 @@ void strncmp_cst (void)
 
 void strncmp_range (void)
 {
-  size_t n = DIFF_MAX;
+  size_t n = DIFF_MAX - 1;
   n = UR (n, n + 1);
 
   T (STR, /* [] */, STR, /* [] */, n);
diff --git a/gcc/testsuite/gcc.dg/attr-nonstring-4.c b/gcc/testsuite/gcc.dg/attr-nonstring-4.c
index f2416c16e83..641e2ca20a0 100644
--- a/gcc/testsuite/gcc.dg/attr-nonstring-4.c
+++ b/gcc/testsuite/gcc.dg/attr-nonstring-4.c
@@ -29,7 +29,10 @@ void sink (size_t);
 
 void strnlen_cst (void)
 {
-  size_t n = DIFF_MAX;
+  /* The largest object is DIFF_MAX - 1 bytes so that the difference
+     between a pointer just past the last byte and the first is no
+     more than DIFF_MAX.  */
+  size_t n = DIFF_MAX - 1;
 
   T (STR, /* [] */, n);
   T (STR, /* [] */, n + 1);    /* { dg-warning "specified bound \[0-9\]+ exceeds maximum object size \[0-9\]+" } */
@@ -47,7 +50,7 @@ void strnlen_cst (void)
 
 void strnlen_range (void)
 {
-  size_t n = DIFF_MAX;
+  size_t n = DIFF_MAX - 1;
   n = UR (n, n + 1);
 
   T (STR, /* [] */, n);
diff --git a/gcc/testsuite/gcc.dg/strlenopt-40.c b/gcc/testsuite/gcc.dg/strlenopt-40.c
index 7a97ebb8fe5..f9fcf7a0404 100644
--- a/gcc/testsuite/gcc.dg/strlenopt-40.c
+++ b/gcc/testsuite/gcc.dg/strlenopt-40.c
@@ -118,17 +118,15 @@ void elim_global_arrays (int i)
   /* Even when treating a multi-dimensional array as a single string
      the length must be less DIFF_MAX - (ax_3[i] - ax_3[0]) but GCC
      doesn't do that computation yet so avoid testing it.  */
-  ELIM_TRUE (strlen (ax_3[0]) < DIFF_MAX);
-  ELIM_TRUE (strlen (ax_3[1]) < DIFF_MAX);
-  ELIM_TRUE (strlen (ax_3[9]) < DIFF_MAX);
-  ELIM_TRUE (strlen (ax_3[i]) < DIFF_MAX);
+  ELIM_TRUE (strlen (ax_3[0]) < DIFF_MAX - 1);
+  ELIM_TRUE (strlen (ax_3[1]) < DIFF_MAX - 1);
+  ELIM_TRUE (strlen (ax_3[9]) < DIFF_MAX - 1);
+  ELIM_TRUE (strlen (ax_3[i]) < DIFF_MAX - 1);
 
   ELIM_TRUE (strlen (a3) < sizeof a3);
   ELIM_TRUE (strlen (a7) < sizeof a7);
 
-  ELIM_TRUE (strlen (ax) != DIFF_MAX);
-  /* ELIM_TRUE (strlen (ax) != DIFF_MAX - 1); */
-  /* ELIM_TRUE (strlen (ax) < DIFF_MAX - 1); */
+  ELIM_TRUE (strlen (ax) != DIFF_MAX - 1);
 }
 
 void elim_pointer_to_arrays (void)
@@ -137,21 +135,21 @@ void elim_pointer_to_arrays (void)
      to a smaller array to point to an object of a bigger type so
      the strlen range optimization must assume each array pointer
      points effectively to an array of an unknown bound.  */
-  ELIM_TRUE (strlen (*pa7) < DIFF_MAX);
-  ELIM_TRUE (strlen (*pa5) < DIFF_MAX);
-  ELIM_TRUE (strlen (*pa3) < DIFF_MAX);
+  ELIM_TRUE (strlen (*pa7) < DIFF_MAX - 1);
+  ELIM_TRUE (strlen (*pa5) < DIFF_MAX - 1);
+  ELIM_TRUE (strlen (*pa3) < DIFF_MAX - 1);
 
-  ELIM_TRUE (strlen ((*pa7_3)[0]) < DIFF_MAX);
-  ELIM_TRUE (strlen ((*pa7_3)[1]) < DIFF_MAX);
-  ELIM_TRUE (strlen ((*pa7_3)[6]) < DIFF_MAX);
+  ELIM_TRUE (strlen ((*pa7_3)[0]) < DIFF_MAX - 1);
+  ELIM_TRUE (strlen ((*pa7_3)[1]) < DIFF_MAX - 1);
+  ELIM_TRUE (strlen ((*pa7_3)[6]) < DIFF_MAX - 1);
 
-  ELIM_TRUE (strlen ((*pax_3)[0]) < DIFF_MAX);
-  ELIM_TRUE (strlen ((*pax_3)[1]) < DIFF_MAX);
-  ELIM_TRUE (strlen ((*pax_3)[9]) < DIFF_MAX);
+  ELIM_TRUE (strlen ((*pax_3)[0]) < DIFF_MAX - 1);
+  ELIM_TRUE (strlen ((*pax_3)[1]) < DIFF_MAX - 1);
+  ELIM_TRUE (strlen ((*pax_3)[9]) < DIFF_MAX - 1);
 
-  ELIM_TRUE (strlen ((*pa5_7)[0]) < DIFF_MAX);
-  ELIM_TRUE (strlen ((*pa5_7)[1]) < DIFF_MAX);
-  ELIM_TRUE (strlen ((*pa5_7)[4]) < DIFF_MAX);
+  ELIM_TRUE (strlen ((*pa5_7)[0]) < DIFF_MAX - 1);
+  ELIM_TRUE (strlen ((*pa5_7)[1]) < DIFF_MAX - 1);
+  ELIM_TRUE (strlen ((*pa5_7)[4]) < DIFF_MAX - 1);
 }
 
 void elim_global_arrays_and_strings (int i)
@@ -258,9 +256,9 @@ void keep_global_arrays (int i)
   KEEP (strlen (a7 + i) < 2);
 
   /* The length of an array of unknown size may be as large as
-     DIFF_MAX - 2.  */
-  KEEP (strlen (ax) != DIFF_MAX - 2);
-  KEEP (strlen (ax) < DIFF_MAX - 2);
+     DIFF_MAX - 3.  */
+  KEEP (strlen (ax) != DIFF_MAX - 3);
+  KEEP (strlen (ax) < DIFF_MAX - 3);
   KEEP (strlen (ax) < 999);
   KEEP (strlen (ax) < 1);
 }
@@ -396,26 +394,26 @@ void keep_member_arrays_ptr (struct MemArrays0 *ma0,
   /* Same as above.  */
   KEEP (strlen (ma0[i].a5_7[i]) > sizeof ma0[i].a5_7);
 
-  KEEP (strlen (ma0->a0) < DIFF_MAX - 2);
+  KEEP (strlen (ma0->a0) < DIFF_MAX - 3);
   KEEP (strlen (ma0->a0) < 999);
   KEEP (strlen (ma0->a0) < 1);
 
-  KEEP (strlen (max->ax) < DIFF_MAX - 2);
+  KEEP (strlen (max->ax) < DIFF_MAX - 3);
   KEEP (strlen (max->ax) < 999);
   KEEP (strlen (max->ax) < 1);
 
-  KEEP (strlen (ma7->a7) < DIFF_MAX - 2);
+  KEEP (strlen (ma7->a7) < DIFF_MAX - 3);
   KEEP (strlen (ma7->a7) < 999);
   KEEP (strlen (ma7->a7) < 1);
 }
 
 void keep_pointers (const char *s)
 {
-  KEEP (strlen (ptr) < DIFF_MAX - 2);
+  KEEP (strlen (ptr) < DIFF_MAX - 3);
   KEEP (strlen (ptr) < 999);
   KEEP (strlen (ptr) < 1);
 
-  KEEP (strlen (s) < DIFF_MAX - 2);
+  KEEP (strlen (s) < DIFF_MAX - 3);
   KEEP (strlen (s) < 999);
   KEEP (strlen (s) < 1);
 }

Reply via email to