From 68c29da4c5a6e3f5443c3b2bfc0ee6d2f44002c8 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Mon, 27 Oct 2014 19:34:10 +0000 Subject: [PATCH] Do not insert asan paddings after fields that have flexible arrays. Summary: We should avoid a tail padding not only if the last field has zero size but also if the last field is a struct with a flexible array. If/when http://reviews.llvm.org/D5478 is committed, this will also handle the case of structs with zero-sized arrays. Reviewers: majnemer, rsmith Reviewed By: rsmith Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D5924 llvm-svn: 220708 --- clang/lib/AST/RecordLayoutBuilder.cpp | 11 +++++--- .../CodeGen/sanitize-address-field-padding.cpp | 30 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index d8966f8..72ccebd 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1331,8 +1331,13 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // Layout each field, for now, just sequentially, respecting alignment. In // the future, this will need to be tweakable by targets. bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true); - for (const auto *Field : D->fields()) - LayoutField(Field, InsertExtraPadding); + bool HasFlexibleArrayMember = D->hasFlexibleArrayMember(); + for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) { + auto Next(I); + ++Next; + LayoutField(*I, + InsertExtraPadding && (Next != End || !HasFlexibleArrayMember)); + } } // Rounds the specified size to have it a multiple of the char size. @@ -1750,7 +1755,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D, Context.toBits(UnpackedFieldOffset), Context.toBits(UnpackedFieldAlign), FieldPacked, D); - if (InsertExtraPadding && !FieldSize.isZero()) { + if (InsertExtraPadding) { CharUnits ASanAlignment = CharUnits::fromQuantity(8); CharUnits ExtraSizeForAsan = ASanAlignment; if (FieldSize % ASanAlignment) diff --git a/clang/test/CodeGen/sanitize-address-field-padding.cpp b/clang/test/CodeGen/sanitize-address-field-padding.cpp index 009605c..5f049bb 100644 --- a/clang/test/CodeGen/sanitize-address-field-padding.cpp +++ b/clang/test/CodeGen/sanitize-address-field-padding.cpp @@ -55,6 +55,36 @@ class ClassWithVirtualBase : public virtual VirtualBase { ClassWithVirtualBase class_with_virtual_base; +class WithFlexibleArray1 { + public: + WithFlexibleArray1() {} + ~WithFlexibleArray1() {} + int make_it_non_standard_layout; + private: + char private1[33]; + int flexible[]; // Don't insert padding after this field. +}; + +WithFlexibleArray1 with_flexible_array1; +// CHECK: %class.WithFlexibleArray1 = type { i32, [12 x i8], [33 x i8], [15 x i8], [0 x i32] } + +class WithFlexibleArray2 { + public: + char x[21]; + WithFlexibleArray1 flex1; // Don't insert padding after this field. +}; + +WithFlexibleArray2 with_flexible_array2; +// CHECK: %class.WithFlexibleArray2 = type { [21 x i8], [11 x i8], %class.WithFlexibleArray1 } + +class WithFlexibleArray3 { + public: + char x[13]; + WithFlexibleArray2 flex2; // Don't insert padding after this field. +}; + +WithFlexibleArray3 with_flexible_array3; + class Negative1 { public: -- 2.7.4