-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Description
| Previous ID | SR-6468 |
| Radar | rdar://problem/35699277 |
| Original Reporter | derammo (JIRA User) |
| Type | Bug |
| Status | Resolved |
| Resolution | Done |
Attachment: Download
Environment
swift-4.1-DEVELOPMENT-SNAPSHOT-2017-11-23-a.xctoolchain
also happens in Xcode 9.1 as released by Apple:
Additional Detail from JIRA
| Votes | 0 |
| Component/s | Compiler |
| Labels | Bug, Codable |
| Assignee | @slavapestov |
| Priority | Medium |
md5: 44a3722f047bd288f0a7c1c8573bee7e
is duplicated by:
- SR-6507 Encodable in combination with class inheritance and computed properties generates unexpected behaviour
- SR-7090 Crashing with EXC_BAD_ACCESS after decoding Codable subclass
- SR-7156 Synthesized instance methods result in vtable-related crashes
Issue Description:
Inheriting from a class that has some of its "Codable" protocol implementation synthesized automatically can lead to invalid code. Specifically, the derived class ends up with code that accesses out of the bounds of the table of methods when trying to invoke a method on an instance of the derived class.
I verified this by disassembly. Instead of fetching the address of the first getter, it fetches a small number (which seems to be the table size) that is located 8 bytes to the left of the correct information. Then it calls this address, which obviously faults.
In this example, you see if it fetching the 0x18 (presumably table size) instead of the valid address of the getter 0x0106bdf460, which is stored right after it.
(lldb) dis -l
-> 10 func testInheritedGeneratedInitializerFromCodableSynthesizer() {
-> 11 let instance = TestPartiallySynthesizedDerivedClass(arg1: 1, arg2: 2)
-> 12 let getting = instance.derivedMember
testUnit`testCompiler.testInheritedGeneratedInitializerFromCodableSynthesizer():
-> 0x106bb6af9 <+41>: movq (%rax), %rsi
0x106bb6afc <+44>: movq 0xb0(%rsi), %rsi
0x106bb6b03 <+51>: movq %rax, %r13
0x106bb6b06 <+54>: movq %rax, -0x18(%rbp)
0x106bb6b0a <+58>: callq *%rsi
(lldb) nexti
(lldb) register read rsi
rsi = 0x0000000106c46550 type metadata for testUnit.TestPartiallySynthesizedDerivedClass
(lldb) memory read 0x106C46600
0x106c46600: 18 00 00 00 00 00 00 00 60 f4 bd 06 01 00 00 00 ........`.......
0x106c46610: b0 f4 bd 06 01 00 00 00 30 f5 bd 06 01 00 00 00 ........0.......
(lldb) dis -a 0106bdf460
testUnit`_T08testUnit36TestPartiallySynthesizedDerivedClassC13derivedMemberSbvg:
0x106bdf460 <+0>: pushq %rbp
0x106bdf461 <+1>: movq %rsp, %rbp
0x106bdf464 <+4>: subq $0x40, %rsp
0x106bdf468 <+8>: movq %r13, -0x8(%rbp)
0x106bdf46c <+12>: movq %r13, %rax
0x106bdf46f <+15>: addq $0x20, %rax
0x106bdf473 <+19>: xorl %ecx, %ecx
0x106bdf475 <+21>: movl %ecx, %edx
0x106bdf477 <+23>: leaq -0x20(%rbp), %rsi
0x106bdf47b <+27>: movq %rax, %rdi
0x106bdf47e <+30>: movq %rsi, -0x28(%rbp)
0x106bdf482 <+34>: movq %rdx, -0x30(%rbp)
0x106bdf486 <+38>: movq -0x30(%rbp), %rcx
0x106bdf48a <+42>: movq %r13, -0x38(%rbp)
0x106bdf48e <+46>: callq 0x106c278de ; symbol stub for: swift_beginAccess
0x106bdf493 <+51>: movq -0x38(%rbp), %rax
0x106bdf497 <+55>: movb 0x20(%rax), %al
0x106bdf49a <+58>: movq -0x28(%rbp), %rdi
0x106bdf49e <+62>: movb %al, -0x39(%rbp)
0x106bdf4a1 <+65>: callq 0x106c2790e ; symbol stub for: swift_endAccess
0x106bdf4a6 <+70>: movb -0x39(%rbp), %al
0x106bdf4a9 <+73>: addq $0x40, %rsp
0x106bdf4ad <+77>: popq %rbp
0x106bdf4ae <+78>: retq The problem is reliably reproduced but extremely specific. Adding explicit support for Codable in the base class makes it go away. Adding explicit support for Codable in the derived class (by adding decode(from) also) also makes it go away. The classes must be in a separate file from the caller for this to fail.
The attached files reproduce the problem 100% of the time as a unit test.