Bug 693719 - Attached PDF file does not display
Summary: Attached PDF file does not display
Status: RESOLVED FIXED
Alias: None
Product: MuPDF
Classification: Unclassified
Component: mupdf (show other bugs)
Version: master
Hardware: All All
: P4 major
Assignee: MuPDF bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-03-20 22:17 UTC by Till Kamppeter
Modified: 2015-04-02 09:16 UTC (History)
6 users (show)

See Also:
Customer:
Word Size: ---


Attachments
Offending PDF file (574.49 KB, application/pdf)
2013-03-20 22:17 UTC, Till Kamppeter
Details
Smaller PDF exhibiting the bug (262 bytes, application/pdf)
2013-10-17 10:45 UTC, Michaël Cadilhac
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Till Kamppeter 2013-03-20 22:17:52 UTC
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.
Comment 1 Robin Watts 2013-03-21 17:32:09 UTC
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.
Comment 2 zeniko 2013-03-21 19:32:44 UTC
(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).
Comment 3 Till Kamppeter 2013-03-21 20:28:38 UTC
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 ...
Comment 4 Michaël Cadilhac 2013-10-17 10:39:13 UTC
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).
Comment 5 Michaël Cadilhac 2013-10-17 10:45:33 UTC
Created attachment 10328 [details]
Smaller PDF exhibiting the bug
Comment 6 Matt Holgate 2014-06-23 02:46:53 UTC
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.
Comment 7 Matt Holgate 2014-06-23 02:48:25 UTC
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)
Comment 8 Matt Holgate 2014-06-23 03:18:41 UTC
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)
Comment 9 Robin Watts 2015-04-02 09:16:16 UTC
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.