Created attachment 9369 [details] Offending PDF file The attached PDF does not render with MuPDF (http://ghostscript.com/~robin/MuPDF-9.apk) installed on the Nexus 7 with Android 4.2. The screen simply stays black and one cannot return to the file selection view with the back arrow button at the bottom. I got the file from Poppler developer Albert Astals Cid and he is not able to display the file with MuPDF under Linux on a PC.
This file has no page tree, so MuPDF can't read it. MuPDF-9.apk on my android device exits back to the file list. Looking at the code I see a mistake there where we have an uncaught exception so we will probably exit nastily. Fixed here: commit c373cc8e44b0b32220088059ada161edfd0a2d78 Author: Robin Watts <robin.watts@artifex.com> Date: Thu Mar 21 16:50:52 2013 +0000 Bug 693719: Android: Catch exceptions when counting pages. Return 0. Check for this case when opening a PDF and give a nice dialogue. Fix the nice dialogue code so that it doesn't crash afterwards due to a null mSearchTask. http://ghostscript.com/~robin/MuPDF-10.apk is online with the fix in now.
(In reply to comment #1) > This file has no page tree, so MuPDF can't read it. Actually, the file has a page tree (Adobe Reader reads it just fine), MuPDF just fails to find it during repairs because it doesn't look for the proper /Root (it rejects 120 0 R and doesn't use the proper 114 0 R instead).
The problem of hanging MuPDF is indeed fixed now, but not this bug. Zeniko tells in comment #2 that the file displays with Adobe Reader. Reopening ...
If I'm reading the standard correctly, only the last trailer section should be considered. In this PDF, the last trailer section gives a /Root pointing to an array. Falling back to a previous trailer seems to be pretty standard (evince, acroread — qpdf also, but it in fact reads the first trailer only). If I read Poppler's code correctly, the strategy goes like this: das_root <- null for all the trailers, sequencially: if trailer->root is a dict das_root <- trailer->root. Hence they ensure that the selected root is *at least* a dict. This can be tested using the PDF I will attach next: change 4 0 to an empty dict, and evince fails to open it (acroread too). I don't think the standard specifies a behavior in such a case, hence I believe this bug report is an enhancement request. I exhibit the problem with a smaller test case with the following attachment. Evince and acroread open it smoothly, while MuPDF fails (rightfully IMO).
Created attachment 10328 [details] Smaller PDF exhibiting the bug
There seems to be one remaining Android-specific problem here. If I press the back button while the 'Cannot open document' dialog is on screen, then press back again, the app crashes. I'll attempt to fix that, then we can remove the Android tag from this bug as the general document loading problem also occurs on other platforms.
06-23 10:44:32.000: E/MessageQueue-JNI(9372): java.lang.NullPointerException 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at com.artifex.mupdfdemo.MuPDFActivity.onBackPressed(MuPDFActivity.java:1086) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.app.Activity.onKeyUp(Activity.java:2193) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.KeyEvent.dispatch(KeyEvent.java:2664) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.app.Activity.dispatchKeyEvent(Activity.java:2423) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1962) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:3845) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3819) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3392) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3442) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3411) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3518) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3419) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3575) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3392) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3442) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3411) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3419) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3392) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3442) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3411) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3551) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3711) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2010) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1704) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1695) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:1987) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.os.MessageQueue.nativePollOnce(Native Method) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.os.MessageQueue.next(MessageQueue.java:138) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.os.Looper.loop(Looper.java:123) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at android.app.ActivityThread.main(ActivityThread.java:5001) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at java.lang.reflect.Method.invokeNative(Native Method) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at java.lang.reflect.Method.invoke(Method.java:515) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 06-23 10:44:32.000: E/MessageQueue-JNI(9372): at dalvik.system.NativeStart.main(Native Method)
commit 5e8cbb16509767f42072739b7f13391051191f89 Author: Matt Holgate <matt@emobix.co.uk> Date: Mon Jun 23 11:06:25 2014 +0100 Fix crash when dismissing 'Cannot open document' dialog with back button, then pressing back button again. I've also added an onCancel() handler, so that the back button only needs to be pressed once to return to the file picker view. Spotted while looking at bug #693719 - Attached PDF file does not display (edit)
Fixed in: commit 485058dbc22c2b181bd044bae9721224f016d568 Author: Robin Watts <robin.watts@artifex.com> Date: Tue Mar 31 19:42:57 2015 +0100 Bug 693719: Improve repairing of files with broken trailers. When repairing a file we keep track of the most recent 'Root' entry we have found. Only accept a new Root entry as a replacement if it is a dictionary. and commit 1e6b1183733fed840e96fb1a43e1429e5b84b508 Author: Robin Watts <robin.watts@artifex.com> Date: Wed Apr 1 15:49:15 2015 +0100 Bug 693719: Attempt #2. Broken trailer repair. Calling pdf_is_dict causes the file to seek. This is a bad thing in a process that is running through the file. It's doubly bad, as the thing it seeks to read may not be there as it might not have been repaired yet. So, instead of just keeping the 'most recent root that is a dictionary', we change to keeping a list of the roots we have found while parsing the doc. At the end we then check for the most recent one that is a dictionary and use that.