Change ArrayIndexOutOfBounds message to exclude information about char and index.
The information doesn't seem very useful for debugging, and it isn't possible to have the char+index be accurate while allowing for fast-failure paths that can know an input string won't fit but can't possibly know the exact character that is at the boundary without doing a lot of expensive work instead.
The unit test already reflected the oddity that what it printed wasn't consistent/predictable depending on if it was going to hit a fast-path or not, and that test is fixed to shown the consistency after this change.
PiperOrigin-RevId: 810954092
diff --git a/java/core/src/main/java/com/google/protobuf/Utf8.java b/java/core/src/main/java/com/google/protobuf/Utf8.java
index d520067..3e06c0c 100644
--- a/java/core/src/main/java/com/google/protobuf/Utf8.java
+++ b/java/core/src/main/java/com/google/protobuf/Utf8.java
@@ -824,12 +824,8 @@
Java8Compatibility.position(out, outIx);
} catch (IndexOutOfBoundsException e) {
// TODO: Consider making the API throw IndexOutOfBoundsException instead.
-
- // If we failed in the outer ASCII loop, outIx will not have been updated. In this case,
- // use inIx to determine the bad write index.
- int badWriteIndex = out.position() + Math.max(inIx, outIx - out.position() + 1);
throw new ArrayIndexOutOfBoundsException(
- "Failed writing " + in.charAt(inIx) + " at index " + badWriteIndex);
+ "Not enough space in output buffer to encode UTF-8 string");
}
}
}
@@ -1058,7 +1054,8 @@
&& (i + 1 == in.length() || !Character.isSurrogatePair(c, in.charAt(i + 1)))) {
throw new UnpairedSurrogateException(i, utf16Length);
}
- throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
+ throw new ArrayIndexOutOfBoundsException(
+ "Not enough space in output buffer to encode UTF-8 string");
}
}
return j;
@@ -1449,7 +1446,7 @@
if (inLimit > length || out.length - length < offset) {
// Not even enough room for an ASCII-encoded string.
throw new ArrayIndexOutOfBoundsException(
- "Failed writing " + in.charAt(inLimit - 1) + " at index " + (offset + length));
+ "Not enough space in output buffer to encode UTF-8 string");
}
// Designed to take advantage of
@@ -1494,7 +1491,8 @@
throw new UnpairedSurrogateException(inIx, inLimit);
}
// Not enough space in the output buffer.
- throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + outIx);
+ throw new ArrayIndexOutOfBoundsException(
+ "Not enough space in output buffer to encode UTF-8 string");
}
}
@@ -1511,7 +1509,7 @@
if (inLimit > outLimit - outIx) {
// Not even enough room for an ASCII-encoded string.
throw new ArrayIndexOutOfBoundsException(
- "Failed writing " + in.charAt(inLimit - 1) + " at index " + out.limit());
+ "Not enough space in output buffer to encode UTF-8 string");
}
// Designed to take advantage of
@@ -1557,7 +1555,8 @@
throw new UnpairedSurrogateException(inIx, inLimit);
}
// Not enough space in the output buffer.
- throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + outIx);
+ throw new ArrayIndexOutOfBoundsException(
+ "Not enough space in output buffer to encode UTF-8 string");
}
}
diff --git a/java/core/src/test/java/com/google/protobuf/Utf8Test.java b/java/core/src/test/java/com/google/protobuf/Utf8Test.java
index 2a53e82..fd50ba2 100644
--- a/java/core/src/test/java/com/google/protobuf/Utf8Test.java
+++ b/java/core/src/test/java/com/google/protobuf/Utf8Test.java
@@ -142,8 +142,9 @@
} catch (Throwable t) {
// Expected
assertThat(t).isInstanceOf(clazz);
- // byte[] + safeProcessor will not exit early. We can't match the message since we don't
- // know which char/index due to random input.
+ assertThat(t)
+ .hasMessageThat()
+ .isEqualTo("Not enough space in output buffer to encode UTF-8 string");
}
try {
@@ -151,9 +152,9 @@
assertWithMessage("Expected " + clazz.getSimpleName()).fail();
} catch (Throwable t) {
assertThat(t).isInstanceOf(clazz);
- // byte[] + unsafeProcessor will exit early, so we have can match the message.
- String pattern = "Failed writing (.) at index " + length;
- assertThat(t).hasMessageThat().matches(pattern);
+ assertThat(t)
+ .hasMessageThat()
+ .isEqualTo("Not enough space in output buffer to encode UTF-8 string");
}
try {
@@ -162,8 +163,9 @@
} catch (Throwable t) {
// Expected
assertThat(t).isInstanceOf(clazz);
- // ByteBuffer + safeProcessor will not exit early. We can't match the message since we don't
- // know which char/index due to random input.
+ assertThat(t)
+ .hasMessageThat()
+ .isEqualTo("Not enough space in output buffer to encode UTF-8 string");
}
try {
@@ -172,8 +174,9 @@
} catch (Throwable t) {
// Expected
assertThat(t).isInstanceOf(clazz);
- // ByteBuffer + safeProcessor will not exit early. We can't match the message since we don't
- // know which char/index due to random input.
+ assertThat(t)
+ .hasMessageThat()
+ .isEqualTo("Not enough space in output buffer to encode UTF-8 string");
}
try {
@@ -182,13 +185,9 @@
} catch (Throwable t) {
// Expected
assertThat(t).isInstanceOf(clazz);
- // Direct ByteBuffer + unsafeProcessor will exit early if it's not on Android, so we can
- // match the message. On Android, a direct ByteBuffer will have hasArray() being true and
- // it will take a different code path and produces a different message.
- if (!Android.isOnAndroidDevice()) {
- String pattern = "Failed writing (.) at index " + length;
- assertThat(t).hasMessageThat().matches(pattern);
- }
+ assertThat(t)
+ .hasMessageThat()
+ .isEqualTo("Not enough space in output buffer to encode UTF-8 string");
}
}