From 1bd78126b14f556fd30226163899bdb5835e8b53 Mon Sep 17 00:00:00 2001 From: arostovtsev Date: Tue, 13 Jul 2021 15:00:21 -0700 Subject: [PATCH] Catch an unchecked exception which may be thrown by Strings.repeat() To provide a nicer error message for the user. Otherwise, we'd get an UncheckedEvalException without a Starlark stack trace. RELNOTES: None. PiperOrigin-RevId: 384559307 --- src/main/java/net/starlark/java/eval/EvalUtils.java | 11 +++++++++-- .../java/net/starlark/java/eval/testdata/list.star | 1 + .../net/starlark/java/eval/testdata/string_misc.star | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/starlark/java/eval/EvalUtils.java b/src/main/java/net/starlark/java/eval/EvalUtils.java index ae92efbd5234fb..e5c3cb20caf093 100644 --- a/src/main/java/net/starlark/java/eval/EvalUtils.java +++ b/src/main/java/net/starlark/java/eval/EvalUtils.java @@ -391,8 +391,15 @@ private static int compare(Object x, Object y) throws EvalException { private static String repeatString(String s, StarlarkInt in) throws EvalException { int n = in.toInt("repeat"); - // TODO(adonovan): reject unreasonably large n. - return n <= 0 ? "" : Strings.repeat(s, n); + if (n <= 0) { + return ""; + } else if ((long) s.length() * (long) n > Integer.MAX_VALUE) { + // Would exceed max length of a java String (and would cause an undocumented + // ArrayIndexOutOfBoundsException to be thrown in Strings.repeat()). + throw Starlark.errorf("excessive repeat (%d * %d characters)", s.length(), n); + } else { + return Strings.repeat(s, n); + } } /** Evaluates a unary operation. */ diff --git a/src/test/java/net/starlark/java/eval/testdata/list.star b/src/test/java/net/starlark/java/eval/testdata/list.star index c0f4370cc1a709..455cd0f7f93223 100644 --- a/src/test/java/net/starlark/java/eval/testdata/list.star +++ b/src/test/java/net/starlark/java/eval/testdata/list.star @@ -63,3 +63,4 @@ assert_eq(3 * [1, 2, 3], [1, 2, 3, 1, 2, 3, 1, 2, 3]) assert_eq([1, 2, 3] * -1, []) assert_eq([1, 2, 3] * 0, []) assert_fails(lambda: [1] * (1 << 35), "got 34359738368 for repeat, want value in signed 32-bit range") +assert_fails(lambda: [1, 2, 3] * (1 << 30), "excessive repeat \\(3 \\* 1073741824 elements\\)") diff --git a/src/test/java/net/starlark/java/eval/testdata/string_misc.star b/src/test/java/net/starlark/java/eval/testdata/string_misc.star index 96de437e586f98..1d294da5d5c6f5 100644 --- a/src/test/java/net/starlark/java/eval/testdata/string_misc.star +++ b/src/test/java/net/starlark/java/eval/testdata/string_misc.star @@ -176,3 +176,4 @@ assert_eq(3 * "abc", "abcabcabc") assert_eq("abc" * 0, "") assert_eq("abc" * -1, "") assert_fails(lambda: "abc" * (1 << 35), "got 34359738368 for repeat, want value in signed 32-bit range") +assert_fails(lambda: "abc" * (1 << 30), "excessive repeat \\(3 \\* 1073741824 characters\\)")