Bug 508105 - Error evaluating expressions with multibyte characters

Don't use String.getBytes() and use indices from that array to call
String.getCharAt(). If text contains multibyte characters, the length of
the byte array will be higher as the number of characters, so the code
will fail with StringIndexOutOfBoundsException sooner or later.

Change-Id: Id68a7bec339c2076a2d291291a3d104c65021f69
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GeneralEvalTests.java b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GeneralEvalTests.java
index 6dfdd34..196bff8 100644
--- a/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GeneralEvalTests.java
+++ b/org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/eval/GeneralEvalTests.java
@@ -465,4 +465,71 @@
 			terminateAndRemove(thread);
 		}
 	}
+
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=508105
+	 *
+	 * @throws Exception
+	 */
+	public void testMultiByteCharacters() throws Exception {
+		IJavaThread thread = null;
+		try {
+			String typename = "bug401270";
+			createLineBreakpoint(25, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("the program did not suspend", thread);
+
+			String snippet = "int äüßö€ = 1; { if(äüßö€ < 0) return false; }; return äüßö€ > 0";
+			IValue value = doEval(thread, snippet);
+			assertTrue("The result of 'int äüßö€ = 1; { if(äüßö€ < 0) return false; }; return äüßö€ > 0' should be true", Boolean.parseBoolean(value.getValueString()));
+
+			snippet = "\"ทดสอบ\".length() > 0";
+			value = doEval(thread, snippet);
+			assertTrue("The result of '\"ทดสอบ\".length() > 0' should be true", Boolean.parseBoolean(value.getValueString()));
+
+			snippet = "return \"ทดสอบ\".length() == 5";
+			value = doEval(thread, snippet);
+			assertTrue("The result of 'return \"ทดสอบ\".length() == 5' should be true", Boolean.parseBoolean(value.getValueString()));
+
+			snippet = "{return \"ทดสอบ\".length() != 5;}";
+			value = doEval(thread, snippet);
+			assertFalse("The result of '{return \"ทดสอบ\".length() != 5;}' should be false", Boolean.parseBoolean(value.getValueString()));
+
+			snippet = "{/**/};\n{return \"ทดสอบ\".charAt(0) == '\\\\';}";
+			value = doEval(thread, snippet);
+			assertFalse("The result of '{/**/};\\n{return \\\"ทดสอบ\\\".charAt(0) == '\\\\\\\\';}' should be false", Boolean.parseBoolean(value.getValueString()));
+		}
+		finally {
+			removeAllBreakpoints();
+			terminateAndRemove(thread);
+		}
+	}
+
+	/**
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=508105
+	 *
+	 * @throws Exception
+	 */
+	public void XtestAReturn() throws Exception {
+		IJavaThread thread = null;
+		try {
+			String typename = "bug401270";
+			createLineBreakpoint(25, typename);
+			thread = launchToBreakpoint(typename);
+			assertNotNull("the program did not suspend", thread);
+
+			String snippet = "int a = 1; return a > 0";
+			IValue value = doEval(thread, snippet);
+			assertTrue("The result of 'int a = 1; return a > 0' should be true", Boolean.parseBoolean(value.getValueString()));
+
+			snippet = "int areturn = 1; return areturn > 0";
+			value = doEval(thread, snippet);
+			assertTrue("The result of 'int areturn = 1; return areturn > 0' should be true", Boolean.parseBoolean(value.getValueString()));
+
+		}
+		finally {
+			removeAllBreakpoints();
+			terminateAndRemove(thread);
+		}
+	}
 }
diff --git a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java
index 4e10c8d..9c68780 100644
--- a/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java
+++ b/org.eclipse.jdt.debug/eval/org/eclipse/jdt/internal/debug/eval/ast/engine/EvaluationSourceGenerator.java
@@ -80,7 +80,7 @@
 	protected String getCompleteSnippet(String codeSnippet) {
 		codeSnippet = codeSnippet.trim(); // remove whitespaces at the end
 		boolean inString = false;
-		byte[] chars = codeSnippet.getBytes();
+		char[] chars = codeSnippet.toCharArray();
 
 		int semicolonIndex = -1;
 		int lastSemilcolonIndex = -1;