JDK-8165909 : JavaScript to Java String conversion is not correct
  • Type: Bug
  • Component: javafx
  • Sub-Component: web
  • Affected Version: 8u112,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-09-12
  • Updated: 2017-08-07
  • Resolved: 2017-01-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u151Fixed 9Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
While testing the latest build of FX for JDK 9, I was doing some random navigation on yahoo.com with HelloWebView and got an IOOBE on one of the pages. The exception message does not cause the application to fail, and the content seems to be rendered correctly in spite of the error.

To reproduce, run HelloWebView as follows:

$ java HelloWebView http://www.thedailyheel.com/20-stars-you-didnt-know-were-twins/?utm_source=yahoo&utm_medium=All&utm_campaign=DHCelebTwins0829

java.lang.StringIndexOutOfBoundsException: begin 0, end 4, length 2
	at java.lang.String.checkBoundsBeginEnd(String.java:3122)
	at java.lang.String.substring(String.java:1910)
	at com.sun.javafx.webkit.prism.WCGraphicsPrismContext.drawString(WCGraphicsPrismContext.java:960)
	at com.sun.webkit.graphics.GraphicsDecoder.decode(GraphicsDecoder.java:290)
	at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:91)
	at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:102)
	at com.sun.webkit.graphics.WCImage.flushRQ(WCImage.java:52)
	at com.sun.javafx.webkit.prism.RTImage.lambda$getPixelBuffer$2(RTImage.java:163)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:514)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:514)
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:307)
	at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1158)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:632)
	at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
	at java.lang.Thread.run(Thread.java:804)
java.lang.StringIndexOutOfBoundsException: begin 0, end 4, length 2
	at java.lang.String.checkBoundsBeginEnd(String.java:3122)
	at java.lang.String.substring(String.java:1910)
	at com.sun.javafx.webkit.prism.WCGraphicsPrismContext.drawString(WCGraphicsPrismContext.java:960)
	at com.sun.webkit.graphics.GraphicsDecoder.decode(GraphicsDecoder.java:290)
	at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:91)
	at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:102)
	at com.sun.webkit.graphics.WCImage.flushRQ(WCImage.java:52)
	at com.sun.javafx.webkit.prism.RTImage.lambda$getPixelBuffer$2(RTImage.java:163)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:514)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:514)
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:307)
	at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1158)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:632)
	at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
	at java.lang.Thread.run(Thread.java:804)


2)
       java.lang.StringIndexOutOfBoundsException: String index out of range: 4
        at java.lang.String.substring(String.java:1963)
        at com.sun.javafx.webkit.prism.WCFontImpl.getGlyphsAndAdvances(WCFontImpl.java:120)
        at com.sun.webkit.network.URLLoader.twkDidReceiveData(Native Method)
        at com.sun.webkit.network.URLLoader.notifyDidReceiveData(URLLoader.java:844)
        at com.sun.webkit.network.URLLoader.lambda$didReceiveData$4(URLLoader.java:819)
        at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
        at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$null$3(WinApplication.java:191)
        at java.lang.Thread.run(Thread.java:745)


Comments
hangeset: b727f0fe7dcf user: arajkumar date: Sun Jan 08 00:05:02 2017 +0530 description: 8165909: JavaScript to Java String conversion is not correct Reviewed-by: ghb, mbilla, kcr URL: http://hg.openjdk.java.net/openjfx/9-dev/rt/rev/b727f0fe7dcf
07-01-2017

Thanks [~kcr]. Created a follow-up bug JDK-8172278.
05-01-2017

+1 Unrelated to this bug, I noticed that the emoji in the simplifies test does not display properly on Mac, but displays as two rectangles. This is not a regression, since it displays incorrectly with JDK 8 GA, too. Please file a follow-on bug (P4) for this.
04-01-2017

Thanks [~arajkumar] +1
03-01-2017

Thanks [~ghb] and [~mbilla] for reviewing the fix. >> Do we no need call releaseLocal() at below place since it is direct ASCII ?? Issue is only seen with UTF, ASCII string is taken care by Java's modified UTF-8 representation[1]. [1] https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html#modified_utf_8_strings
03-01-2017

Updated unit test to cover null and empty String cases: http://cr.openjdk.java.net/~arajkumar/8165909/webrev.01
03-01-2017

Do we no need call releaseLocal() at below place since it is direct ASCII ?? 1) ./WebCore/platform/java/TextCodecJava.cpp, jstring s = env->NewStringUTF(encoding.name()); 2) in ./WebCore/bridge/jni/jsc/JavaFieldJSC.cpp fieldTypeName = env->NewStringUTF("<Unknown>"); Also in case of empty string, is it required add another test case ? /WebCore/bridge/jni/jsc/JNIUtilityPrivate.cpp:69: env->NewStringUTF(""));
03-01-2017

+1
03-01-2017

http://cr.openjdk.java.net/~arajkumar/8165909/webrev
02-01-2017

During r187486 WebKit migration, we started to use "NewStringUTF" instead of "NewString" JNI function due to unavailability of "String::deprecatedCharacters" function[1]. WTF::String can be in 2 forms, 8-bit Latin1 format or 16-bit unicode format. WTF::String::utf8 converts any form of the string to UTF-8 encoding and it is used while converting WTF::String to Java String. But Java String understands only modified UTF-8 chars[2], not the standard UTF-8. So it is better to use "NewString" function to covert to Java String. if (is8Bit()) { UChar uChars[length()]; for each latin1 char { uChars[i] = latin1[i]; } return env->NewString(uChars, length()); } [1] https://trac.webkit.org/changeset/166120 [2] https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/types.html#modified_utf_8_strings
02-01-2017

By using JNI's NewString(...) for unicode JavaString conversion seems to be fixing the Exception and behaviour is similar to 8ga. diff -r 2a0ff4fb858d modules/javafx.web/src/main/native/Source/WTF/wtf/java/StringJava.cpp --- a/modules/javafx.web/src/main/native/Source/WTF/wtf/java/StringJava.cpp Fri Dec 23 10:48:55 2016 -0800 +++ b/modules/javafx.web/src/main/native/Source/WTF/wtf/java/StringJava.cpp Fri Dec 30 15:49:40 2016 +0530 @@ -34,7 +34,11 @@ if (isNull()) { return NULL; } else { - return env->NewStringUTF(utf8().data()); + if (is8Bit()) { + return env->NewStringUTF(utf8().data()); + } else { + return env->NewString(characters16(), length()); + } } } But still smiles are not displayed(only empty square boxes are displayed) , other browser like Chrome and safari displays.
30-12-2016

Exception happens when webkit trying to render a 2 char length string with offset of (0, 4) which is wrong. In the given test case, string has been created using 4 unicode chars (String.fromCharCode(55356, 57221, 55356, 57343)), but after converting from WTF String to Java String it shows the length as 2.
30-12-2016

Issue is seen with pages which uses wordpress emoji library http://emojione.com
27-12-2016

Only the exception print started coming after JDK-8160769 because of below change, - log.fine("Exception occurred: " + e); + e.printStackTrace(System.err);
27-12-2016

Emoji rendering is not happening even on 8ga, so it is not a regression of JDK-8160769.
27-12-2016

Below is a reduced test code to reproduce the issue, <html> <head> <body> <style> canvas { width: 100px; height: 100px; } </style> <script type="text/javascript"> var f = document.createElement("canvas"), g = f.getContext("2d"); var text = String.fromCharCode(55356, 57221, 55356, 57343); g.font="72px Arial"; g.fillText(text, 50, 50); document.body.appendChild(f); </script> </body> </html> The above piece of code shows the emoji on Chrome, but nothing is visible in FX WebView.
27-12-2016

Approved by component triage team to defer
02-12-2016

SQE: JDK 9: OK to defer
02-12-2016

9-client-defer-candidate: Checked the webpage for any rendering issues due to the exception and page rendered without any issues (Comments section at bottom of the page is not seen in hellowebview compared to chrome browser.) Also compared the page with 8u60 and 8u102 and comments section is not seen in earlier JDK versions too(might be due to different content delivery). So there is no regression in JDK 9. Hence considering the little significance of this issue, moving the issue to tbd_major.
29-11-2016

GraphicsDecoder.decode method calls WCGraphicsPrismContext.drawString method. While calling drawString method, GraphicsDecoder passes "bdata.getString(buf.getInt())" passes as 2nd parameter and "buf.getInt(), buf.getInt()" as from and to positions. GraphicsDecoder.decode(WCGraphicsManager gm, WCGraphicsContext gc, BufferData bdata) { case DRAWSTRING: gc.drawString( (WCFont) gm.getRef(buf.getInt()), bdata.getString(buf.getInt()), (buf.getInt() == -1), // rtl flag buf.getInt(), buf.getInt(), // from and to positions buf.getFloat(), buf.getFloat());// (x,y) position break; } ByteBuffer.getInt() method reads the next four bytes at buffer's current position, But in this case ByteBuffer (buf) is only of length 2 and WCGraphicsPrismContext.drawString raises StringIndexOutOfBoundsException while calling substring at below code: TextLayout layout = TextUtilities.createLayout( str.substring(from, to), f.getPlatformFont());
01-10-2016

UR SQE OK to defer it from PSU16_04
15-09-2016

[~kcr] Yes..the exception i mentioned (tried in JDK 9) in comments is unrelated to the bug report I tried with 8u112 b07 in windows 64 bit and able to reproduce the StringOutOfBoundsException. java.lang.StringIndexOutOfBoundsException: String index out of range: 4 at java.lang.String.substring(String.java:1963) at com.sun.javafx.webkit.prism.WCGraphicsPrismContext.drawString(WCGraphicsPrismContext.java:960) at com.sun.webkit.graphics.GraphicsDecoder.decode(GraphicsDecoder.java:290) at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:91) at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:102) at com.sun.webkit.graphics.WCImage.flushRQ(WCImage.java:52) at com.sun.javafx.webkit.prism.RTImage.lambda$getPixelBuffer$77(RTImage.java:163) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125) at java.lang.Thread.run(Thread.java:745)
13-09-2016

While scrolling on yahoo.com page, got below exception which is same as JDK-8162339 Sep 13, 2016 12:04:10 PM com.sun.webkit.network.URLLoader doRun WARNING: Unexpected error java.lang.IllegalArgumentException: Last unit does not have enough valid bits at java.util.Base64$Decoder.decode0(Base64.java:734) at java.util.Base64$Decoder.decode(Base64.java:526) at java.util.Base64$Decoder.decode(Base64.java:549) at com.sun.webkit.network.data.DataURLConnection.<init>(DataURLConnection.java:124) at com.sun.webkit.network.data.Handler.openConnection(Handler.java:41) at java.net.URL.openConnection(URL.java:1046) at com.sun.webkit.network.URLLoader.doRun(URLLoader.java:158) at com.sun.webkit.network.URLLoader.lambda$run$0(URLLoader.java:129) at java.security.AccessController.doPrivileged(Native Method) at com.sun.webkit.network.URLLoader.run(URLLoader.java:128) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:514) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1158) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:632) at java.lang.Thread.run(Thread.java:804)
13-09-2016

The above exception is unrelated to this bug report. If you scroll yahoo.com with an earlier version of JDK 8u you will see the same exception.
13-09-2016

I bisected this in FX 9-dev and discovered that this regression was caused by the fix for JDK-8160769. I can also confirm that JDK 8u112-b03 does not have this bug and JDK 8u112-b04 does (the fix for JDK-8160769 went into 8u112-b04).
12-09-2016