readium / swift-toolkit

A toolkit for ebooks, audiobooks and comics written in Swift
https://readium.org/mobile/
BSD 3-Clause "New" or "Revised" License
225 stars 96 forks source link

Opening epub crashes with EXC_BAD_ACCESS when parsing language Metadata #327

Closed gavin-bruce closed 10 months ago

gavin-bruce commented 11 months ago

Bug Report

What happened?

I am experiencing an issue with a specific ebook that crashes app when I try to open it. No errors popup up and return back the iPhone Home Screen after the crash.

I've tried several other ebook and they do not have this issue.

I do not believe it is an issue with the ePub file as the ebook opens without issue in other app

Xcode indicate the app crashes here https://github.com/readium/swift-toolkit/blob/45fde57234e8970fa617946d7b549eca83f263b1/Sources/Shared/Publication/Metadata.swift#L243 with the following error: Thread 1: EXC_BAD_ACCESS (code=2, address=0x16b8a7ff0)

Expected behavior

The TestApp opens the epub file successfully and the ebook content is displayed.

How to reproduce?

I am unable to share the ebook as it contains copyright material.

In the test app import an ebook The ebook imports to the library without any issues Open the ebook - App crashes at this point

The ebook itself consist of images and has a total size around 591.2 MB.

Environment

Development environment

macOS: 13.4 platform: arm64 Xcode 14.3.1 Build version 14E300c

Testing device

Additional Context

The content of the console in Xcode

☝️ Readium 2 Log enabled with minimum severity level of [warning].
2023-08-16 14:01:01.578670+0100 TestApp[1336:116137] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x281dc9c20 h=--& v=--& _UIToolbarContentView:0x1038a87e0.width == 0   (active)>",
    "<NSLayoutConstraint:0x281dcdb80 H:|-(0)-[_UIButtonBarStackView:0x1038aa0c0]   (active, names: '|':_UIToolbarContentView:0x1038a87e0 )>",
    "<NSLayoutConstraint:0x281dcdbd0 H:[_UIButtonBarStackView:0x1038aa0c0]-(0)-|   (active, names: '|':_UIToolbarContentView:0x1038a87e0 )>",
    "<NSLayoutConstraint:0x281dc84b0 'IB_Leading_Leading' H:|-(0)-[_UIModernBarButton:0x103a5e250]   (active, names: '|':_UIButtonBarButton:0x103a5e050 )>",
    "<NSLayoutConstraint:0x281dc8a00 'IB_Leading_Leading' H:|-(>=5)-[_UIModernBarButton:0x103a5e940]   (active, names: '|':_UIButtonBarButton:0x103a35e70 )>",
    "<NSLayoutConstraint:0x281dc8500 'IB_Trailing_Trailing' H:[_UIModernBarButton:0x103a5e250]-(>=5)-|   (active, names: '|':_UIButtonBarButton:0x103a5e050 )>",
    "<NSLayoutConstraint:0x281dc8a50 'IB_Trailing_Trailing' H:[_UIModernBarButton:0x103a5e940]-(0)-|   (active, names: '|':_UIButtonBarButton:0x103a35e70 )>",
    "<NSLayoutConstraint:0x281dc8fa0 'UISV-canvas-connection' UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide'.leading == UIView:0x103a3c480.leading   (active)>",
    "<NSLayoutConstraint:0x281dc92c0 'UISV-canvas-connection' UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide'.trailing == UIView:0x103a5f370.trailing   (active)>",
    "<NSLayoutConstraint:0x281dc9310 'UISV-spacing' H:[UIView:0x103a3c480]-(0)-[_UIButtonBarButton:0x103a5e050]   (active)>",
    "<NSLayoutConstraint:0x281dc9360 'UISV-spacing' H:[_UIButtonBarButton:0x103a5e050]-(0)-[UIView:0x103a35cf0]   (active)>",
    "<NSLayoutConstraint:0x281dc93b0 'UISV-spacing' H:[UIView:0x103a35cf0]-(0)-[_UIButtonBarButton:0x103a35e70]   (active)>",
    "<NSLayoutConstraint:0x281dc9400 'UISV-spacing' H:[_UIButtonBarButton:0x103a35e70]-(0)-[UIView:0x103a5f370]   (active)>",
    "<NSLayoutConstraint:0x281dcda90 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide'](LTR)   (active, names: '|':_UIButtonBarStackView:0x1038aa0c0 )>",
    "<NSLayoutConstraint:0x281dcdb30 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide']-(0)-|(LTR)   (active, names: '|':_UIButtonBarStackView:0x1038aa0c0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x281dc8500 'IB_Trailing_Trailing' H:[_UIModernBarButton:0x103a5e250]-(>=5)-|   (active, names: '|':_UIButtonBarButton:0x103a5e050 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2023-08-16 14:01:01.579203+0100 TestApp[1336:116137] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x281dc9c20 h=--& v=--& _UIToolbarContentView:0x1038a87e0.width == 0   (active)>",
    "<NSLayoutConstraint:0x281dcdb80 H:|-(0)-[_UIButtonBarStackView:0x1038aa0c0]   (active, names: '|':_UIToolbarContentView:0x1038a87e0 )>",
    "<NSLayoutConstraint:0x281dcdbd0 H:[_UIButtonBarStackView:0x1038aa0c0]-(0)-|   (active, names: '|':_UIToolbarContentView:0x1038a87e0 )>",
    "<NSLayoutConstraint:0x281dc8a00 'IB_Leading_Leading' H:|-(>=5)-[_UIModernBarButton:0x103a5e940]   (active, names: '|':_UIButtonBarButton:0x103a35e70 )>",
    "<NSLayoutConstraint:0x281dc8a50 'IB_Trailing_Trailing' H:[_UIModernBarButton:0x103a5e940]-(0)-|   (active, names: '|':_UIButtonBarButton:0x103a35e70 )>",
    "<NSLayoutConstraint:0x281dc8fa0 'UISV-canvas-connection' UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide'.leading == UIView:0x103a3c480.leading   (active)>",
    "<NSLayoutConstraint:0x281dc92c0 'UISV-canvas-connection' UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide'.trailing == UIView:0x103a5f370.trailing   (active)>",
    "<NSLayoutConstraint:0x281dc9310 'UISV-spacing' H:[UIView:0x103a3c480]-(0)-[_UIButtonBarButton:0x103a5e050]   (active)>",
    "<NSLayoutConstraint:0x281dc9360 'UISV-spacing' H:[_UIButtonBarButton:0x103a5e050]-(0)-[UIView:0x103a35cf0]   (active)>",
    "<NSLayoutConstraint:0x281dc93b0 'UISV-spacing' H:[UIView:0x103a35cf0]-(0)-[_UIButtonBarButton:0x103a35e70]   (active)>",
    "<NSLayoutConstraint:0x281dc9400 'UISV-spacing' H:[_UIButtonBarButton:0x103a35e70]-(0)-[UIView:0x103a5f370]   (active)>",
    "<NSLayoutConstraint:0x281dcda90 'UIView-leftMargin-guide-constraint' H:|-(0)-[UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide'](LTR)   (active, names: '|':_UIButtonBarStackView:0x1038aa0c0 )>",
    "<NSLayoutConstraint:0x281dcdb30 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide']-(0)-|(LTR)   (active, names: '|':_UIButtonBarStackView:0x1038aa0c0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x281dc8a50 'IB_Trailing_Trailing' H:[_UIModernBarButton:0x103a5e940]-(0)-|   (active, names: '|':_UIButtonBarButton:0x103a35e70 )>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2023-08-16 14:01:01.590041+0100 TestApp[1336:116137] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x281dc9cc0 h=--& v=--& _UIToolbarContentView:0x1038a87e0.height == 0   (active)>",
    "<NSLayoutConstraint:0x281dcdc20 V:|-(0)-[_UIButtonBarStackView:0x1038aa0c0]   (active, names: '|':_UIToolbarContentView:0x1038a87e0 )>",
    "<NSLayoutConstraint:0x281dcdc70 _UIButtonBarStackView:0x1038aa0c0.bottom == _UIToolbarContentView:0x1038a87e0.bottom   (active)>",
    "<NSLayoutConstraint:0x281df37a0 UIImageView:0x103a5e750.centerY == _UIModernBarButton:0x103a5e250.centerY   (active)>",
    "<NSLayoutConstraint:0x281dc8780 'IB_Baseline_Baseline' _UIModernBarButton:0x103a5e250.lastBaseline == UILayoutGuide:0x280781180'UIViewLayoutMarginsGuide'.bottom   (active)>",
    "<NSLayoutConstraint:0x281dc87d0 'IB_Top_Top' V:|-(>=0)-[_UIModernBarButton:0x103a5e250]   (active, names: '|':_UIButtonBarButton:0x103a5e050 )>",
    "<NSLayoutConstraint:0x281dc8910 'UIButtonBar.maximumAlignmentSize' _UIButtonBarButton:0x103a5e050.height == UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide'.height   (active)>",
    "<NSLayoutConstraint:0x281dcdae0 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide']-(0)-|   (active, names: '|':_UIButtonBarStackView:0x1038aa0c0 )>",
    "<NSLayoutConstraint:0x281dc86e0 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x280781180'UIViewLayoutMarginsGuide']-(11)-|   (active, names: '|':_UIButtonBarButton:0x103a5e050 )>",
    "<NSLayoutConstraint:0x281dcda40 'UIView-topMargin-guide-constraint' V:|-(0)-[UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide']   (active, names: '|':_UIButtonBarStackView:0x1038aa0c0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x281df37a0 UIImageView:0x103a5e750.centerY == _UIModernBarButton:0x103a5e250.centerY   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2023-08-16 14:01:01.590779+0100 TestApp[1336:116137] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x281dc9cc0 h=--& v=--& _UIToolbarContentView:0x1038a87e0.height == 0   (active)>",
    "<NSLayoutConstraint:0x281dcdc20 V:|-(0)-[_UIButtonBarStackView:0x1038aa0c0]   (active, names: '|':_UIToolbarContentView:0x1038a87e0 )>",
    "<NSLayoutConstraint:0x281dcdc70 _UIButtonBarStackView:0x1038aa0c0.bottom == _UIToolbarContentView:0x1038a87e0.bottom   (active)>",
    "<NSLayoutConstraint:0x281dcf750 UIImageView:0x103a5ef40.centerY == _UIModernBarButton:0x103a5e940.centerY   (active)>",
    "<NSLayoutConstraint:0x281dc8cd0 'IB_Baseline_Baseline' _UIModernBarButton:0x103a5e940.lastBaseline == UILayoutGuide:0x280781880'UIViewLayoutMarginsGuide'.bottom   (active)>",
    "<NSLayoutConstraint:0x281dc8d20 'IB_Top_Top' V:|-(>=0)-[_UIModernBarButton:0x103a5e940]   (active, names: '|':_UIButtonBarButton:0x103a35e70 )>",
    "<NSLayoutConstraint:0x281dc8e60 'UIButtonBar.maximumAlignmentSize' _UIButtonBarButton:0x103a35e70.height == UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide'.height   (active)>",
    "<NSLayoutConstraint:0x281dcdae0 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide']-(0)-|   (active, names: '|':_UIButtonBarStackView:0x1038aa0c0 )>",
    "<NSLayoutConstraint:0x281dc8c30 'UIView-bottomMargin-guide-constraint' V:[UILayoutGuide:0x280781880'UIViewLayoutMarginsGuide']-(11)-|   (active, names: '|':_UIButtonBarButton:0x103a35e70 )>",
    "<NSLayoutConstraint:0x281dcda40 'UIView-topMargin-guide-constraint' V:|-(0)-[UILayoutGuide:0x280784700'UIViewLayoutMarginsGuide']   (active, names: '|':_UIButtonBarStackView:0x1038aa0c0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x281dcf750 UIImageView:0x103a5ef40.centerY == _UIModernBarButton:0x103a5e940.centerY   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2023-08-16 14:01:01.612401+0100 TestApp[1336:116400] [catalog] Unable to list voice folder
mickael-menu commented 11 months ago

Hi, could you share the contents of the OPF file in the EPUB? (You can unzip it like a regular ZIP archive)

gavin-bruce commented 11 months ago

Hi,

Here the OPF file content.zip

gavin-bruce commented 11 months ago

I've some further investigation and it appear this line is the opf file is causing the issue

<meta property="rendition:spread">both</meta>

Once this line was removed the ebook loaded without issue in the test app

mickael-menu commented 10 months ago

I built a fake EPUB with the content.opf you shared but could open it without issue in the Navigator. I also don't see how

<meta property="rendition:spread">both</meta>

could crash the app here:

https://github.com/readium/swift-toolkit/blob/45fde57234e8970fa617946d7b549eca83f263b1/Sources/Shared/Publication/Metadata.swift#L243

Would you be able to share this book privately with me? You can send it to my Gmail address (mickael.menu).

gavin-bruce commented 10 months ago

I'm not able to send the ebook, but have sent you a modified copy of the epub version I have removed all the copyrighted images and replace them. I've check this epub file and it still crashes for me.

The email subject is GitHub issue 327

mickael-menu commented 10 months ago

Somehow I can still open this ebook, from the tag 2.5.1. I started the app with the iOS simulator, drag and dropped the book and then tapped on it.

Simulator Screenshot - iPhone 14 Pro - 2023-09-01 at 17 59 03

gavin-bruce commented 10 months ago

Feel free to close this issue. I have tested the ebook I've sent again the Iphone SE again, and can confirm it does it indeed crash for me. I don't think I'll be able to provide the original ebook so feel to close this as I am not sure what else I can provide.