Removing a PDFPage from a PDFDocument throws an exception unless all pages loaded

Originator:matias.piipari
Number:rdar://14081212 Date Originated:06/06/2013
Status:Open Resolved:
Product:OSX Product Version:10.8.4
Classification:Serious bug Reproducible:Always
 
06-Jun-2013 04:05 PM Matias Piipari:
Summary:

Removing a PDFPage from a PDFDocument with -removePageAtIndex: throws an exception unless all pages for the document have been loaded with -pageAtIndex: before removing the page. 

- Issue is specific to OSX 10.8.4.
- Can be worked around by sending -pageAtIndex: for all of the document's pages from 0..(doc.pageCount - 1) before sending -removePageAtIndex:
- Example application demonstrating the bug and a workaround for it is attached, and can be found from:
https://dl.dropboxusercontent.com/u/511181/PDFPageRemovalBugDemo1084.zip

Steps to Reproduce:

1) Load a PDF document

    PDFDocument *doc =
        [[PDFDocument alloc] initWithURL:
            [[NSBundle mainBundle] URLForResource:@"chicken" withExtension:@"pdf"]];

2) Remove a page from the document

    [doc removePageAtIndex:0]; // causes an exception because -annotations is sent to a __NSCFNumber instance.



Expected Results:

The PDF page at index 0 was removed from the document.



Actual Results:

An unrecognizer selector exception is thrown somewhere inside -removePageAtIndex:

2013-06-06 15:37:33.595 PDFPageRemovalBugDemo1084[57470:303] -[__NSCFNumber annotations]: unrecognized selector sent to instance 0x287

Full stack trace of the thread:

#0	0x00007fff8d6ee3c6 in objc_exception_throw ()
#1	0x00007fff8807540a in -[NSObject(NSObject) doesNotRecognizeSelector:] ()
#2	0x00007fff87fcd02e in ___forwarding___ ()
#3	0x00007fff87fcce18 in _CF_forwarding_prep_0 ()
#4	0x00007fff81f7afde in -[PDFDocument removePageAtIndex:] ()
#5	0x0000000100001319 in -[MTAppDelegate applicationDidFinishLaunching:] at /Users/mz2/Projects/PDFPageRemovalBugDemo1084/PDFPageRemovalBugDemo1084/MTAppDelegate.m:19

The -removePageAtIndex: part of the stack trace:

PDFKit`-[PDFDocument removePageAtIndex:]:
0x7fff81f7ae46:  pushq  %rbp
0x7fff81f7ae47:  movq   %rsp, %rbp
0x7fff81f7ae4a:  pushq  %r15
0x7fff81f7ae4c:  pushq  %r14
0x7fff81f7ae4e:  pushq  %r13
0x7fff81f7ae50:  pushq  %r12
0x7fff81f7ae52:  pushq  %rbx
0x7fff81f7ae53:  subq   $456, %rsp
0x7fff81f7ae5a:  movq   %rdx, %r14
0x7fff81f7ae5d:  movq   %rdi, %rbx
0x7fff81f7ae60:  movq   %rbx, -456(%rbp)
0x7fff81f7ae67:  movq   701450(%rip), %rax
0x7fff81f7ae6e:  movq   (%rax), %rax
0x7fff81f7ae71:  movq   %rax, -48(%rbp)
0x7fff81f7ae75:  movq   844204(%rip), %rax
0x7fff81f7ae7c:  movq   (%rbx,%rax), %rax
0x7fff81f7ae80:  movq   843841(%rip), %rcx
0x7fff81f7ae87:  cmpq   $0, (%rax,%rcx)
0x7fff81f7ae8c:  je     0x7fff81f7b19a            ; -[PDFDocument removePageAtIndex:] + 852
0x7fff81f7ae92:  movq   801399(%rip), %rsi
0x7fff81f7ae99:  movq   %rbx, %rdi
0x7fff81f7ae9c:  callq  *701718(%rip)
0x7fff81f7aea2:  testb  %al, %al
0x7fff81f7aea4:  je     0x7fff81f7aeb6            ; -[PDFDocument removePageAtIndex:] + 112
0x7fff81f7aea6:  movq   801387(%rip), %rsi
0x7fff81f7aead:  movq   %rbx, %rdi
0x7fff81f7aeb0:  callq  *701698(%rip)
0x7fff81f7aeb6:  movq   800963(%rip), %rsi        ; BZ2_hbCreateDecodeTables + 176
0x7fff81f7aebd:  movq   %rbx, %rdi
0x7fff81f7aec0:  movq   %r14, %rdx
0x7fff81f7aec3:  callq  *701679(%rip)
0x7fff81f7aec9:  movq   %rax, %r15
0x7fff81f7aecc:  testq  %r15, %r15
0x7fff81f7aecf:  je     0x7fff81f7aef8            ; -[PDFDocument removePageAtIndex:] + 178
0x7fff81f7aed1:  movq   800040(%rip), %rsi        ; BZ2_hbMakeCodeLengths + 376
0x7fff81f7aed8:  movq   %r15, %rdi
0x7fff81f7aedb:  callq  *701655(%rip)
0x7fff81f7aee1:  cmpq   %rbx, %rax
0x7fff81f7aee4:  jne    0x7fff81f7aef8            ; -[PDFDocument removePageAtIndex:] + 178
0x7fff81f7aee6:  movq   800147(%rip), %rsi        ; BZ2_hbMakeCodeLengths + 504
0x7fff81f7aeed:  movq   %r15, %rdi
0x7fff81f7aef0:  xorl   %edx, %edx
0x7fff81f7aef2:  callq  *701632(%rip)
0x7fff81f7aef8:  movq   844073(%rip), %rax
0x7fff81f7aeff:  movq   (%rbx,%rax), %rax
0x7fff81f7af03:  movq   843710(%rip), %rcx
0x7fff81f7af0a:  movq   (%rax,%rcx), %rdi
0x7fff81f7af0e:  movq   801299(%rip), %rsi
0x7fff81f7af15:  movq   %r14, %rdx
0x7fff81f7af18:  callq  *701594(%rip)
0x7fff81f7af1e:  movq   844035(%rip), %rax
0x7fff81f7af25:  movq   (%rbx,%rax), %rax
0x7fff81f7af29:  xorps  %xmm0, %xmm0
0x7fff81f7af2c:  movq   843829(%rip), %rdi
0x7fff81f7af33:  leaq   813462(%rip), %rsi        ; copyfile_internal + 1235
0x7fff81f7af3a:  leaq   -112(%rbp), %rdx
0x7fff81f7af3e:  leaq   -240(%rbp), %rcx
0x7fff81f7af45:  movq   %r14, (%rax,%rdi)
0x7fff81f7af49:  movaps %xmm0, -64(%rbp)
0x7fff81f7af4d:  movaps %xmm0, -80(%rbp)
0x7fff81f7af51:  movaps %xmm0, -96(%rbp)
0x7fff81f7af55:  movaps %xmm0, -112(%rbp)
0x7fff81f7af59:  movq   843976(%rip), %rax
0x7fff81f7af60:  movq   (%rbx,%rax), %rax
0x7fff81f7af64:  movq   843613(%rip), %rdi
0x7fff81f7af6b:  movq   (%rax,%rdi), %rdi
0x7fff81f7af6f:  movq   %rdi, -472(%rbp)
0x7fff81f7af76:  movl   $16, %r8d
0x7fff81f7af7c:  callq  *813390(%rip)             ; copyfile_internal + 1235
0x7fff81f7af82:  movq   %rax, -480(%rbp)
0x7fff81f7af89:  testq  %rax, %rax
0x7fff81f7af8c:  je     0x7fff81f7b19a            ; -[PDFDocument removePageAtIndex:] + 852
0x7fff81f7af92:  movq   -96(%rbp), %rax
0x7fff81f7af96:  movq   (%rax), %rax
0x7fff81f7af99:  movq   %rax, -488(%rbp)
0x7fff81f7afa0:  movq   701457(%rip), %r14
0x7fff81f7afa7:  xorl   %ebx, %ebx
0x7fff81f7afa9:  movq   -96(%rbp), %rax
0x7fff81f7afad:  movq   -488(%rbp), %rcx
0x7fff81f7afb4:  cmpq   %rcx, (%rax)
0x7fff81f7afb7:  je     0x7fff81f7afc5            ; -[PDFDocument removePageAtIndex:] + 383
0x7fff81f7afb9:  movq   -472(%rbp), %rdi
0x7fff81f7afc0:  callq  0x7fff81ffa068            ; symbol stub for: objc_enumerationMutation
0x7fff81f7afc5:  movq   -104(%rbp), %rax
0x7fff81f7afc9:  movq   (%rax,%rbx,8), %rdi
0x7fff81f7afcd:  movq   %rbx, -464(%rbp)
0x7fff81f7afd4:  movq   800541(%rip), %rsi        ; BZ2_hbCreateDecodeTables + 40
0x7fff81f7afdb:  callq  *%r14
0x7fff81f7afde:  movq   %rax, %rdi
0x7fff81f7afe1:  movq   800464(%rip), %rbx        ; BZ2_hbAssignCodes + 39
0x7fff81f7afe8:  movq   %rbx, %rsi
0x7fff81f7afeb:  callq  *%r14
0x7fff81f7afee:  xorps  %xmm0, %xmm0
0x7fff81f7aff1:  movaps %xmm0, -256(%rbp)
0x7fff81f7aff8:  movaps %xmm0, -272(%rbp)
0x7fff81f7afff:  movaps %xmm0, -288(%rbp)
0x7fff81f7b006:  movaps %xmm0, -304(%rbp)
0x7fff81f7b00d:  movq   %rax, %rdi
0x7fff81f7b010:  movq   %rbx, %rsi
0x7fff81f7b013:  callq  *%r14
0x7fff81f7b016:  movq   %rax, -440(%rbp)
0x7fff81f7b01d:  movq   %rax, %rdi
0x7fff81f7b020:  leaq   813225(%rip), %rsi        ; copyfile_internal + 1235
0x7fff81f7b027:  leaq   -304(%rbp), %rdx
0x7fff81f7b02e:  leaq   -432(%rbp), %rcx
0x7fff81f7b035:  movl   $16, %r8d
0x7fff81f7b03b:  callq  *813199(%rip)             ; copyfile_internal + 1235
0x7fff81f7b041:  movq   %rax, %r12
0x7fff81f7b044:  testq  %r12, %r12
0x7fff81f7b047:  je     0x7fff81f7b14e            ; -[PDFDocument removePageAtIndex:] + 776
0x7fff81f7b04d:  movq   -288(%rbp), %rax
0x7fff81f7b054:  movq   (%rax), %rax
0x7fff81f7b057:  movq   %rax, -448(%rbp)
0x7fff81f7b05e:  xorl   %r15d, %r15d
0x7fff81f7b061:  movq   -288(%rbp), %rax
0x7fff81f7b068:  movq   -448(%rbp), %rcx
0x7fff81f7b06f:  cmpq   %rcx, (%rax)
0x7fff81f7b072:  je     0x7fff81f7b080            ; -[PDFDocument removePageAtIndex:] + 570
0x7fff81f7b074:  movq   -440(%rbp), %rdi
0x7fff81f7b07b:  callq  0x7fff81ffa068            ; symbol stub for: objc_enumerationMutation
0x7fff81f7b080:  movq   -296(%rbp), %rax
0x7fff81f7b087:  movq   (%rax,%r15,8), %r13
0x7fff81f7b08b:  movq   813654(%rip), %rdi        ; copyfile_internal + 1771
0x7fff81f7b092:  leaq   813287(%rip), %rsi        ; copyfile_internal + 1411
0x7fff81f7b099:  callq  *813281(%rip)             ; copyfile_internal + 1411
0x7fff81f7b09f:  leaq   813306(%rip), %rsi        ; copyfile_internal + 1443
0x7fff81f7b0a6:  movq   %r13, %rdi
0x7fff81f7b0a9:  movq   %rax, %rdx
0x7fff81f7b0ac:  callq  *813294(%rip)             ; copyfile_internal + 1443
0x7fff81f7b0b2:  testb  %al, %al
0x7fff81f7b0b4:  je     0x7fff81f7b10e            ; -[PDFDocument removePageAtIndex:] + 712
0x7fff81f7b0b6:  movq   %r13, %rdi
0x7fff81f7b0b9:  movq   800880(%rip), %rsi
0x7fff81f7b0c0:  callq  *%r14
0x7fff81f7b0c3:  movq   %rax, %rdi
0x7fff81f7b0c6:  movq   800251(%rip), %rsi        ; BZ2_hbAssignCodes + 55
0x7fff81f7b0cd:  callq  *%r14
0x7fff81f7b0d0:  movq   %rax, %rdi
0x7fff81f7b0d3:  callq  0x7fff81ffa4dc            ; symbol stub for: CGPDFPageGetPageNumber
0x7fff81f7b0d8:  movq   %rax, %rbx
0x7fff81f7b0db:  movq   -456(%rbp), %rdi
0x7fff81f7b0e2:  movq   800527(%rip), %rsi        ; BZ2_hbCreateDecodeTables + 296
0x7fff81f7b0e9:  callq  *%r14
0x7fff81f7b0ec:  cmpq   %rax, %rbx
0x7fff81f7b0ef:  jbe    0x7fff81f7b10e            ; -[PDFDocument removePageAtIndex:] + 712
0x7fff81f7b0f1:  movq   %r13, %rdi
0x7fff81f7b0f4:  movq   800821(%rip), %rsi
0x7fff81f7b0fb:  callq  *%r14
0x7fff81f7b0fe:  movq   %rax, %rdi
0x7fff81f7b101:  movq   800816(%rip), %rsi
0x7fff81f7b108:  movq   %r13, %rdx
0x7fff81f7b10b:  callq  *%r14
0x7fff81f7b10e:  incq   %r15
0x7fff81f7b111:  cmpq   %r12, %r15
0x7fff81f7b114:  jb     0x7fff81f7b061            ; -[PDFDocument removePageAtIndex:] + 539
0x7fff81f7b11a:  movq   -440(%rbp), %rdi
0x7fff81f7b121:  leaq   812968(%rip), %rsi        ; copyfile_internal + 1235
0x7fff81f7b128:  leaq   -304(%rbp), %rdx
0x7fff81f7b12f:  leaq   -432(%rbp), %rcx
0x7fff81f7b136:  movl   $16, %r8d
0x7fff81f7b13c:  callq  *812942(%rip)             ; copyfile_internal + 1235
0x7fff81f7b142:  movq   %rax, %r12
0x7fff81f7b145:  testq  %r12, %r12
0x7fff81f7b148:  jne    0x7fff81f7b05e            ; -[PDFDocument removePageAtIndex:] + 536
0x7fff81f7b14e:  movq   -464(%rbp), %rbx
0x7fff81f7b155:  incq   %rbx
0x7fff81f7b158:  cmpq   -480(%rbp), %rbx
0x7fff81f7b15f:  jb     0x7fff81f7afa9            ; -[PDFDocument removePageAtIndex:] + 355
0x7fff81f7b165:  movq   -472(%rbp), %rdi
0x7fff81f7b16c:  leaq   812893(%rip), %rsi        ; copyfile_internal + 1235
0x7fff81f7b173:  leaq   -112(%rbp), %rdx
0x7fff81f7b177:  leaq   -240(%rbp), %rcx
0x7fff81f7b17e:  movl   $16, %r8d
0x7fff81f7b184:  callq  *812870(%rip)             ; copyfile_internal + 1235
0x7fff81f7b18a:  movq   %rax, -480(%rbp)
0x7fff81f7b191:  testq  %rax, %rax
0x7fff81f7b194:  jne    0x7fff81f7afa7            ; -[PDFDocument removePageAtIndex:] + 353
0x7fff81f7b19a:  movq   700631(%rip), %rax
0x7fff81f7b1a1:  movq   (%rax), %rax
0x7fff81f7b1a4:  cmpq   -48(%rbp), %rax
0x7fff81f7b1a8:  jne    0x7fff81f7b1bc            ; -[PDFDocument removePageAtIndex:] + 886
0x7fff81f7b1aa:  addq   $456, %rsp
0x7fff81f7b1b1:  popq   %rbx
0x7fff81f7b1b2:  popq   %r12
0x7fff81f7b1b4:  popq   %r13
0x7fff81f7b1b6:  popq   %r14
0x7fff81f7b1b8:  popq   %r15
0x7fff81f7b1ba:  popq   %rbp
0x7fff81f7b1bb:  ret    
0x7fff81f7b1bc:  callq  0x7fff81ff9eca            ; symbol stub for: __stack_chk_fail



Notes:

It is possible to work around the issue by forcing the loading of pages for the document before removing the page. The following code does *not* cause an exception to be thrown:

    PDFDocument *doc =
        [[PDFDocument alloc] initWithURL:
            [[NSBundle mainBundle] URLForResource:@"chicken" withExtension:@"pdf"]];
    
    // forcing the loading of document's pages suppresses the exception throwing 
    for (NSUInteger i = 0, pageCount = doc.pageCount; i < pageCount; i++)
        [doc pageAtIndex:i];
    
    [doc removePageAtIndex:0];

Working around the issue requires loading *all* pages, for instance the following does *not* suppress the error:

    for (NSUInteger i = 0, pageCount = (doc.pageCount - 1); i < pageCount; i++)
        [doc pageAtIndex:i];
    
Inspecting the call stack above, and the class-dumped headers of PDFKit.framework suggests the issue has something to do with how the _pdfPriv->pageArray of a PDFDocument contains pages that have not yet been loaded as NSNumber instances (numbers contain the page number?), not PDFPage instances.

06-Jun-2013 04:05 PM Matias Piipari:
'PDFPageRemovalBugDemo1084.zip' was successfully uploaded

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!