diff --git a/gcc/testsuite/gcc.c-torture/compile/pr110603.c b/gcc/testsuite/gcc.c-torture/compile/pr110603.c
new file mode 100644
index 0000000000000000000000000000000000000000..afcc1a522c234b2f909cc94678ba79cfa19e7a28
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr110603.c
@@ -0,0 +1,16 @@
+/* PR tree-optimization/110603 */
+
+typedef __SIZE_TYPE__ size_t;
+void *memcpy (void *, const void *, size_t);
+int snprintf (char *restrict, size_t, const char *restrict, ...);
+extern char a[2];
+void bar (void);
+
+void
+foo (void)
+{
+  memcpy (a, "12", sizeof (a));
+  int b = snprintf (0, 0, "%s", a);
+  if (b <= 3)
+    bar ();
+}
diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc
index c20db7a0cd958ca82c96ef807e822ab8480261f0..f2fd47d77e89b8831a0ce06c3cf6b0356dbe90e1 100644
--- a/gcc/tree-ssa-strlen.cc
+++ b/gcc/tree-ssa-strlen.cc
@@ -1228,7 +1228,6 @@ get_range_strlen_dynamic (tree src, gimple *stmt,
 		{
 		  tree type = vr.type ();
 		  pdata->minlen = wide_int_to_tree (type, vr.lower_bound ());
-		  pdata->maxlen = wide_int_to_tree (type, vr.upper_bound ());
 		}
 	    }
 	  else
@@ -1253,9 +1252,21 @@ get_range_strlen_dynamic (tree src, gimple *stmt,
 		{
 		  ++off;   /* Increment for the terminating nul.  */
 		  tree toffset = build_int_cst (size_type_node, off);
-		  pdata->maxlen = fold_build2 (MINUS_EXPR, size_type_node, size,
-					       toffset);
-		  pdata->maxbound = pdata->maxlen;
+		  pdata->maxlen = fold_build2 (MINUS_EXPR, size_type_node,
+					       size, toffset);
+		  if (tree_int_cst_lt (pdata->maxlen, pdata->minlen))
+		    /* This can happen when triggering UB, when base is an
+		       array which is known to be filled with at least size
+		       non-zero bytes.  E.g. for
+		       char a[2]; memcpy (a, "12", sizeof a);
+		       We don't want to create an invalid range [2, 1]
+		       where 2 comes from the number of non-zero bytes and
+		       1 from longest valid zero-terminated string that can
+		       be stored in such an array, so pick just one of
+		       those, pdata->minlen.  See PR110603.  */
+		    pdata->maxlen = build_all_ones_cst (size_type_node);
+		  else
+		    pdata->maxbound = pdata->maxlen;
 		}
 	      else	
 		pdata->maxlen = build_all_ones_cst (size_type_node);