New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 618332 link

Starred by 4 users

Issue metadata

Status: Available
Owner: ----
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 3
Type: Bug



Sign in to add a comment

crash when using '0' as port in URL with intercepting WebViewClient

Reported by pqu...@gmail.com, Jun 8 2016

Issue description

THIS TEMPLATE IS FOR FILING BUGS ON THE ANDROID SYSTEM WEBVIEW. GENERAL WEB BUGS SHOULD BE FILED USING A DIFFERENT TEMPLATE!

Device name: HT4BDJT00277 (issue affects multiple devices)
Android version: 6.0.1 (issue affects multiple android versions)
WebView version (from system settings -> Apps -> Android System WebView): 51.0.2704.81
Application: de.walhalla.marvin.vob_a2013 (VOB, BauR, HOAI)
Application version: 1.3.2

Steps to reproduce:
(1) load any URL with explicit '0' as the port via WebView.loadUrl with WebViewClient intercepting all Requests.

Sample project demonstrating the crash:

https://github.com/rincewind/webkit_crash_port0

Sample code (from  any Activity with a WebView's onResume)::

    WebView wv = (WebView) this.findViewById(R.id.webView);
    wv.setWebViewClient(new WebViewClient() {
       @TargetApi(11)
       public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
           InputStream html = new ByteArrayInputStream("<!doctype html><h1>Foo</h1>".getBytes());
           return new WebResourceResponse("text/html", "UTF-8", html);
       }
    });

    wv.loadUrl("http://127.0.0.1:0/foobar");


Expected result:
No crash.

Actual result:
App crashes.

libc    : Fatal signal 6 (SIGABRT), code -6 in tid 8416 (webkit_bug_demo)
DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
DEBUG   : Build fingerprint: 'google/volantis/flounder:6.0.1/MOB30G/2723637:user/release-keys'
DEBUG   : Revision: '0'
DEBUG   : ABI: 'arm64'
DEBUG   : pid: 8416, tid: 8416, name: webkit_bug_demo  >>> de.qdevelop.webkit_bug_demo <<<
DEBUG   : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
DEBUG   : Abort message: '[FATAL:render_process_host_impl.cc(1220)] Check failed: false. 
DEBUG   : '
DEBUG   :     x0   0000000000000000  x1   00000000000020e0  x2   0000000000000006  x3   0000000000000000
DEBUG   :     x4   0000000000000000  x5   0000000000000001  x6   0000000000000000  x7   0000000000000000
DEBUG   :     x8   0000000000000083  x9   0000007fcacb66b2  x10  0000007fcacb6668  x11  0000007fcacb6960
DEBUG   :     x12  0000007fcacb66b1  x13  0000000000000054  x14  0000007f92270358  x15  0000007fa50b9aa8
DEBUG   :     x16  0000007fa50ab6a8  x17  0000007fa506eaec  x18  0000007fa50b9a98  x19  0000007fa54b10a8
DEBUG   :     x20  0000007fa54b0fe8  x21  000000000000000b  x22  0000000000000006  x23  0000000000000000
DEBUG   :     x24  0000007fcacb6f50  x25  0000007f926e3000  x26  0000000000000000  x27  0000000012d68610
DEBUG   :     x28  0000000071703a0e  x29  0000007fcacb69b0  x30  0000007fa506c288
DEBUG   :     sp   0000007fcacb69b0  pc   0000007fa506eaf4  pstate 0000000020000000
DEBUG   : 
DEBUG   : backtrace:
DEBUG   :     #00 pc 000000000006aaf4  /system/lib64/libc.so (tgkill+8)
DEBUG   :     #01 pc 0000000000068284  /system/lib64/libc.so (pthread_kill+68)
DEBUG   :     #02 pc 0000000000021278  /system/lib64/libc.so (raise+28)
DEBUG   :     #03 pc 000000000001ba18  /system/lib64/libc.so (abort+60)
DEBUG   :     #04 pc 0000000002cce1c8  /data/app/com.google.android.webview-2/lib/arm64/libwebviewchromium.so
DEBUG   : 





 

Comment 1 by boliu@chromium.org, Jun 8 2016

why port 0? it's not a valid port

Crash looks like from an invalid IPC. I guess somewhere in IPC code it checks that port number can't be 0. Still should not crash though. Fix is probably to ignore loads going to port 0.

Comment 2 by torne@chromium.org, Jun 8 2016

Can you include the full log (with the breakpad microdump?) From the line number it's probably RenderProcessHostImpl::ShutdownForBadMessage, but the microdump will confirm.

I don't think the network stack allows connecting to port 0 (because while this is technically possible, in practise it's not a sane/reasonable thing to try) - probably this is resulting in a bad IPC coming out somewhere?

Comment 3 by pqu...@gmail.com, Jun 8 2016

Using port '0' came by as more of an accident. And wether zero is an 'invalid' port can be debated ;-)
But since our code intercepts all requests in the WebVewClient, it shouldn't even touch the network. And did work perfectly in versions prior to 51.0.2704.81. 
It's an easy fix on our side, but it probably shouldn't crash either.

I hope the attached logcat output includes what is needed.

(Besides: is there a way to access the tombstone file directly on a not-rooted device?)


microdump_618332.txt
59.3 KB View Download

Comment 4 by torne@chromium.org, Jun 8 2016

The tombstone isn't helpful to us either (the microdump is only emitted into the logs and not part of the tombstone).

If you need a dummy URL to use for request interception you should either use a *totally* invalid URL that isn't even using http: at all (e.g. make up your own URL scheme for your app), or you should use a real URL that you control. Don't hijack a URL that might exist but is outside your control: even if port 0 is valid (which is complicated), your app doesn't control http://127.0.0.1:0/ - it's a port <1024 and so you can't possibly be using it.

You're right that this shouldn't crash, but the most likely way to fix this if Chromium intends for port 0 to be an invalid URL is to not even generate a callback to your code at all (i.e. don't call shouldInterceptRequest in the first place), so relying on this is a bad plan :)

Comment 5 by torne@chromium.org, Jun 8 2016

Components: Internals>Network
Network team: did something intentionally change in M51 about the handling of URLs with port 0?

Comment 6 by pqu...@gmail.com, Jun 8 2016

The 'shouldInterceptRequest' API is not available in Android 2.3.3. For older android devices (and the code is actually quite old) we are using a small HTTP-Server in the App, to serve our own content to the webview. 
When shouldInterceptRequest is available, it is used. I didn't bother to change the URLs for the 'modern' (honeycomb and up) code, since it 'just worked'. The '0' for the port is actually a variable left uninitialized in the modern case when  using 'shouldInterceptRequest'.

That's just to explain, why things are the way they are. I'm fixing the use of port 0 now, but I'd still argue it should not crash (especially since it did not crash up until the latest update).

Comment 7 by torne@chromium.org, Jun 8 2016

Yes, we'll fix it to not crash, but we aren't going to block the M51 release on this, and the fix may well just cause shouldInterceptRequest to not be called (depends what we find when investigating this more) and so your app will still be broken even if it doesn't crash.
re comment #5: 11 months ago, we introduced SchemeHostPort, which (correctly) rejects a port 0 for a generic URL ( https://chromium.googlesource.com/chromium/src/+/d8335d98a4c056ab97c5cdff1e95a7fa2c7dfc10 ). SchemeHostPort is the basis for url::Origin (which compares to the Blink notion of origins, ish), and we've been updating IPCs throughout the codebase to use the proper concepts where appropriate (SchemeHostPort or Origin, explicitly, rather than GURL). 

Given that the Check failure is in RenderProcessHost, it's likely that one of the messages is serializing an Origin via IPC. When the RPH receives it, it sees that the deserialized origin is invalid (0 is invalid), and crashes. That's based on the limited information provided.

It does sound like that the Android side of the equation might not be validating the Origin/SchemeHostPort before serializing, otherwise it would realize it's an invalid message to serialize, so there may be work to be done on the Android side. But I would encourage the WebView folks to dig in on that, since I'm not sure how to get more details.
Cc: mkwst@chromium.org
Status: Available (was: Unconfirmed)
Interesting bits of the stack from the microdump:

 4  libwebviewchromium.so!base::debug::BreakDebugger [debugger_posix.cc : 219 + 0x0]
 5  libwebviewchromium.so!content::RenderProcessHostImpl::ShutdownForBadMessage [render_process_host_impl.cc : 1220 + 0x4]
 6  libwebviewchromium.so!content::bad_message::ReceivedBadMessage [bad_message.cc : 26 + 0xc]
 7  libwebviewchromium.so!content::RenderFrameHostImpl::OnDidCommitProvisionalLoad [render_frame_host_impl.cc : 1031 + 0x4]
 8  libwebviewchromium.so!content::RenderFrameHostImpl::OnMessageReceived [render_frame_host_impl.cc : 500 + 0x8]

So it's DidCommitProvisionalLoad where we're objecting here.

Per #8 it sounds like we should look into this more. Given that WebView allows non-web-standard URLs to be used (like madeupscheme://whatever/anything) this check might be too strict? Or if not, we should at least be rejecting the URL earlier. Either way it shouldn't be dying in this *particular* place, so yes, we should check it out. Thanks for the confirmation.
Cc: sgu...@chromium.org
Owner: ntfschr@chromium.org
Nate, please investigate.
I think we should probably continue to disallow port 0 in a URL since the rest of chromium thinks this is invalid and we haven't had anyone else report this, but as mentioned previously we shouldn't be crashing at the point of serialisation; we should reject the URL earlier in the process.

Comment 13 by boliu@chromium.org, Oct 14 2016

what should "disallow" do exactly? throw an exception? silently ignore the load and maybe an error message? something more clever?
To me, throwing an exception seems inconsistent. Even for totally bogus ports (ex. using a letter or negative number), we don't throw an exception all the way to the top level.

If we call the onReceivedError() callback, then we avoid a crash and also indicate there was some sort of error. In the docs, it states "These errors usually indicate inability to connect to the server," and you could argue that since we wouldn't be able to connect to the server at port 0 anyway, it still fits.

If you try to go to "127.0.0.1:0" by setting window.location or via Chrome's URL bar, it actually says "This site can't be reached" (same as it would for any valid port > 0 that happens to not be serving anything).

Comment 15 by boliu@chromium.org, Oct 14 2016

Hmm, maybe should look into how is the "This site can't be reached" error generated? Why is window.location navigation not triggering the same crash? Maybe there's already a check in the renderer, in which case our check should be there as well.

I think if you want to make this look like a resource error, then I'm guessing blink loader or somewhere thereabouts is the right place to do it.
Hmmm so it appears that the crash only appears when the app actually implements shouldInterceptRequest, not otherwise. Calling loadUrl with port 0 (but without shouldInterceptRequest actually does show the same message as going to any other valid, non-serving port.

So it looks like maybe this is just a bug in shouldInterceptRequest? I'll investigate more closely and see if I can find anything.
Status: Started (was: Available)
Labels: -Pri-2 Pri-3
Cc: -sgu...@chromium.org
Status: Assigned (was: Started)
Cc: ntfschr@chromium.org
Owner: ----
Status: Available (was: Assigned)
Don't have time to work on this. Fairly low priority, since we can't do anything useful in this situation (we either crash or fail silently).

Sign in to add a comment