Skip to content

Commit 6ed2489

Browse files
committed
IRGen: don't stack promote classes for which the layout has not a fixed size
In most cases this was already checked with `ClassLayout::isFixedLayout`. But for classes which are imported from another module and contain implementation-only C-imported stored properties, those properties don't show up in the class layout. Stack promoting such classes will reserve too less space on the stack which leads to all kind of memory corruption problems. The fix is to also check `ClassLayout::isFixedSize`, which returns false for such classes. Fixes a miscompile rdar://131067105
1 parent fc012fd commit 6ed2489

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

lib/IRGen/GenClass.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,8 @@ static llvm::Value *stackPromote(IRGenFunction &IGF,
781781
return nullptr;
782782
if (!FieldLayout.isFixedLayout())
783783
return nullptr;
784+
if (!FieldLayout.isFixedSize())
785+
return nullptr;
784786

785787
// Calculate the total size needed.
786788
// The first part is the size of the class itself.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
// RUN: %target-build-swift -O -wmo -parse-as-library -emit-module -emit-module-path=%t/XMod.swiftmodule -module-name=XMod %t/xmod.swift -I%t -c -o %t/xmod.o
4+
// RUN: %target-build-swift -O -wmo -module-name=Main -I%t %t/main.swift -c -o %t/main.o
5+
// RUN: %target-swiftc_driver %t/main.o %t/xmod.o -o %t/a.out
6+
// RUN: %target-codesign %t/a.out
7+
// RUN: %target-run %t/a.out | %FileCheck %s
8+
9+
//--- module.modulemap
10+
11+
module CModule {
12+
header "c-header.h"
13+
export *
14+
}
15+
16+
17+
//--- c-header.h
18+
19+
struct CS {
20+
int x;
21+
};
22+
23+
//--- xmod.swift
24+
25+
@_implementationOnly import CModule
26+
27+
// The layout of this class does not include the C-imported CS field.
28+
// Therefore it must not be stack-promoted in `testit`. Otherwise the reserved stack space
29+
// would be wrong and the executable would crash.
30+
final public class X {
31+
public var i: Int
32+
var cs: CS? = nil
33+
34+
public init(_ i: Int) { self.i = i }
35+
}
36+
37+
//--- main.swift
38+
39+
import XMod
40+
41+
@inline(never)
42+
func getit(_ x: X, _ y: X) -> Int {
43+
return x.i + y.i
44+
}
45+
46+
@inline(never)
47+
public func testit() -> Int {
48+
return getit(X(27), X(11))
49+
}
50+
51+
// CHECK: 38
52+
print(testit())
53+

0 commit comments

Comments
 (0)