Merge "Make String's fast-path UTF-8 decoder more like icu4c."
diff --git a/luni/src/main/java/java/lang/String.java b/luni/src/main/java/java/lang/String.java
index f3aeb64..89691e7 100644
--- a/luni/src/main/java/java/lang/String.java
+++ b/luni/src/main/java/java/lang/String.java
@@ -282,14 +282,14 @@
 
                     if (idx + utfCount > last) {
                         v[s++] = REPLACEMENT_CHAR;
-                        break;
+                        continue;
                     }
 
                     // Extract usable bits from b0
                     int val = b0 & (0x1f >> (utfCount - 1));
-                    for (int i = 0; i < utfCount; i++) {
+                    for (int i = 0; i < utfCount; ++i) {
                         byte b = d[idx++];
-                        if ((b & 0xC0) != 0x80) {
+                        if ((b & 0xc0) != 0x80) {
                             v[s++] = REPLACEMENT_CHAR;
                             idx--; // Put the input char back
                             continue outer;
diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java
index 2c7d3d4..5aa596f 100644
--- a/luni/src/test/java/libcore/java/lang/StringTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringTest.java
@@ -25,6 +25,7 @@
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
 import java.util.Arrays;
 import java.util.Locale;
 import junit.framework.TestCase;
@@ -326,4 +327,18 @@
     public void test_replaceAll() throws Exception {
         assertEquals("project_Id", "projectId".replaceAll("(?!^)(\\p{Upper})(?!$)", "_$1"));
     }
+
+    // https://code.google.com/p/android/issues/detail?id=23831
+    public void test_23831() throws Exception {
+        byte[] bytes = { (byte) 0xf5, (byte) 0xa9, (byte) 0xea, (byte) 0x21 };
+        String expected = "\ufffd\ufffd\u0021";
+
+        // Since we use icu4c for CharsetDecoder...
+        CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
+        decoder.onMalformedInput(CodingErrorAction.REPLACE);
+        assertEquals(expected, decoder.decode(ByteBuffer.wrap(bytes)).toString());
+
+        // Our fast-path code in String should behave the same...
+        assertEquals(expected, new String(bytes, "UTF-8"));
+    }
 }