Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[randstruct] Don't allow implicit forward decl to stop struct randomi…
…zation If a struct/enum type used in a record doesn't have a forward decl / def, an implicit one is injected into the struct. This stops clang from randomizing the structure in some situations---i.e. when the struct contains only function pointers. So we accept forward decls so they don't prevent randomization. Fixes 60349 Reviewed By: MaskRay, nickdesaulniers Differential Revision: https://reviews.llvm.org/D143300
- Loading branch information
Showing
2 changed files
with
53 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// RUN: %clang_cc1 -triple=x86_64-unknown-linux -emit-llvm -frandomize-layout-seed=1234567890abcdef < %s | FileCheck %s | ||
// PR60349 | ||
|
||
// Clang will add a forward declaration of "struct bar" and "enum qux" to the | ||
// structures. This shouldn't prevent these structures from being randomized. | ||
// So the 'f' element shouldn't be at the start of the structure anymore. | ||
|
||
struct foo { | ||
struct bar *(*f)(void); | ||
struct bar *(*g)(void); | ||
struct bar *(*h)(void); | ||
struct bar *(*i)(void); | ||
struct bar *(*j)(void); | ||
struct bar *(*k)(void); | ||
}; | ||
|
||
// CHECK-LABEL: define {{.*}}@t1( | ||
// CHECK-NOT: getelementptr inbounds %struct.foo, ptr %3, i32 0, i32 0 | ||
struct bar *t1(struct foo *z) { | ||
return z->f(); | ||
} | ||
|
||
struct baz { | ||
enum qux *(*f)(void); | ||
enum qux *(*g)(void); | ||
enum qux *(*h)(void); | ||
enum qux *(*i)(void); | ||
enum qux *(*j)(void); | ||
enum qux *(*k)(void); | ||
}; | ||
|
||
// CHECK-LABEL: define {{.*}}@t2( | ||
// CHECK-NOT: getelementptr inbounds %struct.baz, ptr %3, i32 0, i32 0 | ||
enum qux *t2(struct baz *z) { | ||
return z->f(); | ||
} |