diff options
author | George Burgess IV <george.burgess.iv@gmail.com> | 2016-09-12 23:50:35 +0000 |
---|---|---|
committer | George Burgess IV <george.burgess.iv@gmail.com> | 2016-09-12 23:50:35 +0000 |
commit | f8f632498307d22e10fab0704548b270b15f1e1e (patch) | |
tree | a622ae692aeb374069e2325afa39d6ac217669ed /clang/test/CodeGen/pass-object-size.c | |
parent | a340eff335cfa88403afc2ee81babceaba101965 (diff) | |
download | bcm5719-llvm-f8f632498307d22e10fab0704548b270b15f1e1e.tar.gz bcm5719-llvm-f8f632498307d22e10fab0704548b270b15f1e1e.zip |
[Sema] Fix PR30346: relax __builtin_object_size checks.
This patch makes us act more conservatively when trying to determine
the objectsize for an array at the end of an object. This is in
response to code like the following:
```
struct sockaddr {
/* snip */
char sa_data[14];
};
void foo(const char *s) {
size_t slen = strlen(s) + 1;
size_t added_len = slen <= 14 ? 0 : slen - 14;
struct sockaddr *sa = malloc(sizeof(struct sockaddr) + added_len);
strcpy(sa->sa_data, s);
// ...
}
```
`__builtin_object_size(sa->sa_data, 1)` would return 14, when there
could be more than 14 bytes at `sa->sa_data`.
Code like this is apparently not uncommon. FreeBSD's manual even
explicitly mentions this pattern:
https://www.freebsd.org/doc/en/books/developers-handbook/sockets-essential-functions.html
(section 7.5.1.1.2).
In light of this, we now just give up on any array at the end of an
object if we can't find the object's initial allocation.
I lack numbers for how much more conservative we actually become as a
result of this change, so I chose the fix that would make us as
compatible with GCC as possible. If we want to be more aggressive, I'm
happy to consider some kind of whitelist or something instead.
llvm-svn: 281277
Diffstat (limited to 'clang/test/CodeGen/pass-object-size.c')
-rw-r--r-- | clang/test/CodeGen/pass-object-size.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/clang/test/CodeGen/pass-object-size.c b/clang/test/CodeGen/pass-object-size.c index 6e2bc2090ed..6f5827befa7 100644 --- a/clang/test/CodeGen/pass-object-size.c +++ b/clang/test/CodeGen/pass-object-size.c @@ -59,7 +59,8 @@ void test1() { // CHECK-LABEL: define void @test2 void test2(struct Foo *t) { - // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36) + // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize + // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 [[VAR]]) gi = ObjectSize1(&t->t[1]); // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36) gi = ObjectSize3(&t->t[1]); @@ -168,7 +169,8 @@ void test4(struct Foo *t) { // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}}) gi = NoViableOverloadObjectSize0(&t[1].t[1]); - // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36) + // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize + // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 [[VAR]]) gi = NoViableOverloadObjectSize1(&t[1].t[1]); // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}}) gi = NoViableOverloadObjectSize2(&t[1].t[1]); @@ -274,7 +276,8 @@ void test7() { // CHECK-LABEL: define void @test8 void test8(struct Foo *t) { - // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36) + // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize + // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 [[VAR]]) gi = AsmObjectSize1(&t[1].t[1]); // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36) gi = AsmObjectSize3(&t[1].t[1]); |