Adds missing bound check to String.charAt

Bug: #6942
Bug-Link: https://github.com/gwtproject/gwt/issues/6942
Change-Id: Id7635ec5ddccabdbf12aab536d59c348e656e800
diff --git a/user/super/com/google/gwt/emul/java/lang/String.java b/user/super/com/google/gwt/emul/java/lang/String.java
index 1833b2f..33a3fe3 100644
--- a/user/super/com/google/gwt/emul/java/lang/String.java
+++ b/user/super/com/google/gwt/emul/java/lang/String.java
@@ -18,6 +18,7 @@
 
 import static javaemul.internal.InternalPreconditions.checkCriticalStringBounds;
 import static javaemul.internal.InternalPreconditions.checkNotNull;
+import static javaemul.internal.InternalPreconditions.checkStringElementIndex;
 
 import java.io.Serializable;
 import java.io.UnsupportedEncodingException;
@@ -358,6 +359,7 @@
 
   @Override
   public char charAt(int index) {
+    checkStringElementIndex(index, length());
     return asNativeString().charCodeAt(index);
   }
 
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/InternalPreconditions.java b/user/super/com/google/gwt/emul/javaemul/internal/InternalPreconditions.java
index 6e3f66f..d344435 100644
--- a/user/super/com/google/gwt/emul/javaemul/internal/InternalPreconditions.java
+++ b/user/super/com/google/gwt/emul/javaemul/internal/InternalPreconditions.java
@@ -498,6 +498,24 @@
     }
   }
 
+  public static void checkStringElementIndex(int index, int size) {
+    if (IS_BOUNDS_CHECKED) {
+      checkCriticalStringElementIndex(index, size);
+    } else if (IS_ASSERTED) {
+      try {
+        checkCriticalStringElementIndex(index, size);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  public static void checkCriticalStringElementIndex(int index, int size) {
+    if (index < 0 || index >= size) {
+      throw new StringIndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+    }
+  }
+
   /**
    * Ensures that {@code index} specifies a valid <i>position</i> in a list of
    * size {@code size}. A position index may range from zero to {@code size}, inclusive.
diff --git a/user/test/com/google/gwt/emultest/java/lang/StringTest.java b/user/test/com/google/gwt/emultest/java/lang/StringTest.java
index 87cf441..5265d62 100644
--- a/user/test/com/google/gwt/emultest/java/lang/StringTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/StringTest.java
@@ -39,6 +39,20 @@
 
   public void testCharAt() {
     assertEquals('b', hideFromCompiler("abc").charAt(1));
+
+    try {
+      hideFromCompiler("abc").charAt(-1);
+      fail();
+    } catch (StringIndexOutOfBoundsException ignore) {
+      // expected
+    }
+
+    try {
+      hideFromCompiler("abc").charAt(3);
+      fail();
+    } catch (StringIndexOutOfBoundsException ignore) {
+      // expected
+    }
   }
 
   public void testCodePoint() {