forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Clang] Fix 'counted_by' for nested struct pointers (llvm#110497)
Fix counted_by attribute for cases where the flexible array member is accessed through struct pointer inside another struct: ``` struct variable { int a; int b; int length; short array[] __attribute__((counted_by(length))); }; struct bucket { int a; struct variable *growable; int b; }; ``` __builtin_dynamic_object_size(p->growable->array, 0); This commit makes sure that if the StructBase is both a MemberExpr and a pointer, it is treated as a pointer. Otherwise clang will generate to code to access the address of p->growable intead of loading the value of p->growable->length. Fixes llvm#110385
- Loading branch information
Showing
3 changed files
with
109 additions
and
49 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,62 @@ | ||
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 | ||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wno-missing-declarations -emit-llvm -o - %s | FileCheck %s | ||
|
||
// See #110385 | ||
// Based on reproducer from Kees Cook: | ||
// https://lore.kernel.org/all/202409170436.C3C6E7F7A@keescook/ | ||
|
||
struct variable { | ||
int a; | ||
int b; | ||
int length; | ||
short array[] __attribute__((counted_by(length))); | ||
}; | ||
|
||
struct bucket { | ||
int a; | ||
struct variable *growable; | ||
int b; | ||
}; | ||
|
||
struct bucket2 { | ||
int a; | ||
struct variable growable; | ||
}; | ||
|
||
void init(void * __attribute__((pass_dynamic_object_size(0)))); | ||
|
||
// CHECK-LABEL: define dso_local void @test1( | ||
// CHECK-SAME: ptr nocapture noundef readonly [[FOO:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { | ||
// CHECK-NEXT: entry: | ||
// CHECK-NEXT: [[GROWABLE:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 8 | ||
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[GROWABLE]], align 8, !tbaa [[TBAA2:![0-9]+]] | ||
// CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 12 | ||
// CHECK-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8 | ||
// CHECK-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 | ||
// CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 | ||
// CHECK-NEXT: [[TMP2:%.*]] = shl nsw i64 [[TMP1]], 1 | ||
// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], -1 | ||
// CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i64 [[TMP2]], i64 0 | ||
// CHECK-NEXT: tail call void @init(ptr noundef nonnull [[ARRAY]], i64 noundef [[TMP4]]) #[[ATTR2:[0-9]+]] | ||
// CHECK-NEXT: ret void | ||
// | ||
void test1(struct bucket *foo) { | ||
init(foo->growable->array); | ||
} | ||
|
||
// CHECK-LABEL: define dso_local void @test2( | ||
// CHECK-SAME: ptr noundef [[FOO:%.*]]) local_unnamed_addr #[[ATTR0]] { | ||
// CHECK-NEXT: entry: | ||
// CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 16 | ||
// CHECK-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 12 | ||
// CHECK-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[DOT_COUNTED_BY_GEP]], align 4 | ||
// CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 | ||
// CHECK-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 1 | ||
// CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[DOT_COUNTED_BY_LOAD]], -1 | ||
// CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 [[TMP1]], i64 0 | ||
// CHECK-NEXT: tail call void @init(ptr noundef nonnull [[ARRAY]], i64 noundef [[TMP3]]) #[[ATTR2]] | ||
// CHECK-NEXT: ret void | ||
// | ||
void test2(struct bucket2 *foo) { | ||
init(foo->growable.array); | ||
} |
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