https://github.com/fmayer updated https://github.com/llvm/llvm-project/pull/126163
>From e9f2dbecb2b4836100a565b4c741fc3425d08966 Mon Sep 17 00:00:00 2001 From: Florian Mayer <fma...@google.com> Date: Thu, 6 Feb 2025 16:50:02 -0800 Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?= =?UTF-8?q?itial=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 --- clang/include/clang/Basic/LangOptions.def | 3 ++ clang/include/clang/Basic/LangOptions.h | 13 +++++++++ clang/include/clang/Driver/Options.td | 15 ++++++++++ clang/lib/CodeGen/CGExpr.cpp | 34 +++++++++++++++++++++-- clang/lib/CodeGen/CodeGenFunction.h | 1 + clang/lib/Driver/ToolChains/Clang.cpp | 2 ++ clang/test/CodeGen/bounds-checking-fam.c | 10 +++++++ 7 files changed, 75 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index cb55f09acc076cf..590237eb4f40baf 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -481,6 +481,9 @@ LANGOPT(RawStringLiterals, 1, 1, "Enable or disable raw string literals") ENUM_LANGOPT(StrictFlexArraysLevel, StrictFlexArraysLevelKind, 2, StrictFlexArraysLevelKind::Default, "Rely on strict definition of flexible arrays") +ENUM_LANGOPT(ArrayBoundsStrictFlexArraysLevel, ArrayBoundsStrictFlexArraysLevelKind, 3, + ArrayBoundsStrictFlexArraysLevelKind::None, + "Definition of flexible arrays for bounds checks") COMPATIBLE_VALUE_LANGOPT(MaxTokens, 32, 0, "Max number of tokens per TU or 0") diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index f58a719a45a84de..597165dfc24044c 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -444,6 +444,19 @@ class LangOptionsBase { IncompleteOnly = 3, }; + enum class ArrayBoundsStrictFlexArraysLevelKind { + // Use same StrictFlexArrayLevel as compiler. + None = 0, + /// Any trailing array member is a FAM. + Default = 1, + /// Any trailing array member of undefined, 0, or 1 size is a FAM. + OneZeroOrIncomplete = 2, + /// Any trailing array member of undefined or 0 size is a FAM. + ZeroOrIncomplete = 3, + /// Any trailing array member of undefined size is a FAM. + IncompleteOnly = 4, + }; + /// Controls the various implementations for complex multiplication and // division. enum ComplexRangeKind { diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 77ca2d2aac31be1..3ae768206a34b71 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1533,6 +1533,21 @@ def fstrict_flex_arrays_EQ : Joined<["-"], "fstrict-flex-arrays=">, Group<f_Grou NormalizedValues<["Default", "OneZeroOrIncomplete", "ZeroOrIncomplete", "IncompleteOnly"]>, HelpText<"Enable optimizations based on the strict definition of flexible arrays">, MarshallingInfoEnum<LangOpts<"StrictFlexArraysLevel">, "Default">; +// We might want a different (generally stricter) definition of flexible arrays +// for sanitization than for the codegen. +def fsanitize_array_bounds_strict_flex_arrays_EQ + : Joined<["-"], "fsanitize-bounds-strict-flex-arrays=">, + Group<f_Group>, + MetaVarName<"<n>">, + Values<"none,0,1,2,3">, + LangOpts<"ArrayBoundsStrictFlexArraysLevel">, + Visibility<[ClangOption, CC1Option]>, + NormalizedValuesScope< + "LangOptions::ArrayBoundsStrictFlexArraysLevelKind">, + NormalizedValues<["None", "Default", "OneZeroOrIncomplete", + "ZeroOrIncomplete", "IncompleteOnly"]>, + HelpText<"Set definition of flexible arrays for bounds checks">, + MarshallingInfoEnum<LangOpts<"ArrayBoundsStrictFlexArraysLevel">, "None">; defm apple_pragma_pack : BoolFOption<"apple-pragma-pack", LangOpts<"ApplePragmaPack">, DefaultFalse, PosFlag<SetTrue, [], [ClangOption, CC1Option], diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 1e233c42c8782df..d2540d209f23d9c 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -31,6 +31,7 @@ #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/CodeGenOptions.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" @@ -1192,13 +1193,40 @@ llvm::Value *CodeGenFunction::EmitLoadOfCountedByField( return nullptr; } +LangOptions::StrictFlexArraysLevelKind +CodeGenFunction::effectiveArrayBoundsFlexArraysLevel() { + using StrictFlexArraysLevelKind = LangOptions::StrictFlexArraysLevelKind; + using ArrayBoundsStrictFlexArraysLevelKind = + LangOptions::ArrayBoundsStrictFlexArraysLevelKind; + StrictFlexArraysLevelKind StrictFlexArraysLevel; + switch (getLangOpts().getArrayBoundsStrictFlexArraysLevel()) { + case ArrayBoundsStrictFlexArraysLevelKind::Default: + StrictFlexArraysLevel = StrictFlexArraysLevelKind::Default; + break; + case ArrayBoundsStrictFlexArraysLevelKind::OneZeroOrIncomplete: + StrictFlexArraysLevel = StrictFlexArraysLevelKind::OneZeroOrIncomplete; + break; + case ArrayBoundsStrictFlexArraysLevelKind::ZeroOrIncomplete: + StrictFlexArraysLevel = StrictFlexArraysLevelKind::ZeroOrIncomplete; + break; + case ArrayBoundsStrictFlexArraysLevelKind::IncompleteOnly: + StrictFlexArraysLevel = StrictFlexArraysLevelKind::IncompleteOnly; + break; + case ArrayBoundsStrictFlexArraysLevelKind::None: + StrictFlexArraysLevel = getLangOpts().getStrictFlexArraysLevel(); + break; + } + return StrictFlexArraysLevel; +} + void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index, QualType IndexType, bool Accessed) { assert(SanOpts.has(SanitizerKind::ArrayBounds) && "should not be called unless adding bounds checks"); - const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - getLangOpts().getStrictFlexArraysLevel(); + LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = + effectiveArrayBoundsFlexArraysLevel(); + QualType IndexedType; llvm::Value *Bound = getArrayIndexingBound(*this, Base, IndexedType, StrictFlexArraysLevel); @@ -4383,7 +4411,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, // i.e. "a.b.count", so we shouldn't need the full force of EmitLValue or // similar to emit the correct GEP. const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - getLangOpts().getStrictFlexArraysLevel(); + effectiveArrayBoundsFlexArraysLevel(); if (const auto *ME = dyn_cast<MemberExpr>(Array); ME && diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index e7a5100a9fa2946..62067c8bd9a802b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3315,6 +3315,7 @@ class CodeGenFunction : public CodeGenTypeCache { SanitizerSet SkippedChecks = SanitizerSet(), llvm::Value *ArraySize = nullptr); + LangOptions::StrictFlexArraysLevelKind effectiveArrayBoundsFlexArraysLevel(); /// Emit a check that \p Base points into an array object, which /// we can access at index \p Index. \p Accessed should be \c false if we /// this expression is used as an lvalue, for instance in "&Arr[Idx]". diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index c0891d46b0a62cd..ce937adcb946004 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6976,6 +6976,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_unroll_loops); Args.AddLastArg(CmdArgs, options::OPT_fstrict_flex_arrays_EQ); + Args.AddLastArg(CmdArgs, + options::OPT_fsanitize_array_bounds_strict_flex_arrays_EQ); Args.AddLastArg(CmdArgs, options::OPT_pthread); diff --git a/clang/test/CodeGen/bounds-checking-fam.c b/clang/test/CodeGen/bounds-checking-fam.c index ae211c49ca1f552..dcfe99fa6ff6d91 100644 --- a/clang/test/CodeGen/bounds-checking-fam.c +++ b/clang/test/CodeGen/bounds-checking-fam.c @@ -7,6 +7,16 @@ // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=2 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-2,CXX // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=3 -fsanitize=array-bounds %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-3 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=3 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-3,CXX + +// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize-bounds-strict-flex-arrays=0 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-0,CXX,CXX-STRICT-0 +// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize-bounds-strict-flex-arrays=0 -fsanitize=array-bounds %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-0 +// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize-bounds-strict-flex-arrays=1 -fsanitize=array-bounds %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-1 +// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize-bounds-strict-flex-arrays=1 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-1,CXX +// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize-bounds-strict-flex-arrays=2 -fsanitize=array-bounds %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-2 +// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize-bounds-strict-flex-arrays=2 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-2,CXX +// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize-bounds-strict-flex-arrays=3 -fsanitize=array-bounds %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-3 +// RUN: %clang_cc1 -emit-llvm -triple x86_64 -fsanitize-bounds-strict-flex-arrays=3 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-3,CXX + // Before flexible array member was added to C99, many projects use a // one-element array as the last member of a structure as an alternative. // E.g. https://github.com/python/cpython/issues/84301 >From cde09da532846cce988a6ce68b16b441e369db11 Mon Sep 17 00:00:00 2001 From: Florian Mayer <fma...@google.com> Date: Fri, 7 Feb 2025 17:15:05 -0800 Subject: [PATCH 2/2] nit Created using spr 1.3.4 --- clang/lib/CodeGen/CGExpr.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index d2540d209f23d9c..3f04d0393bf9c6e 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1198,25 +1198,18 @@ CodeGenFunction::effectiveArrayBoundsFlexArraysLevel() { using StrictFlexArraysLevelKind = LangOptions::StrictFlexArraysLevelKind; using ArrayBoundsStrictFlexArraysLevelKind = LangOptions::ArrayBoundsStrictFlexArraysLevelKind; - StrictFlexArraysLevelKind StrictFlexArraysLevel; switch (getLangOpts().getArrayBoundsStrictFlexArraysLevel()) { case ArrayBoundsStrictFlexArraysLevelKind::Default: - StrictFlexArraysLevel = StrictFlexArraysLevelKind::Default; - break; + return StrictFlexArraysLevelKind::Default; case ArrayBoundsStrictFlexArraysLevelKind::OneZeroOrIncomplete: - StrictFlexArraysLevel = StrictFlexArraysLevelKind::OneZeroOrIncomplete; - break; + return StrictFlexArraysLevelKind::OneZeroOrIncomplete; case ArrayBoundsStrictFlexArraysLevelKind::ZeroOrIncomplete: - StrictFlexArraysLevel = StrictFlexArraysLevelKind::ZeroOrIncomplete; - break; + return StrictFlexArraysLevelKind::ZeroOrIncomplete; case ArrayBoundsStrictFlexArraysLevelKind::IncompleteOnly: - StrictFlexArraysLevel = StrictFlexArraysLevelKind::IncompleteOnly; - break; + return StrictFlexArraysLevelKind::IncompleteOnly; case ArrayBoundsStrictFlexArraysLevelKind::None: - StrictFlexArraysLevel = getLangOpts().getStrictFlexArraysLevel(); - break; + return getLangOpts().getStrictFlexArraysLevel(); } - return StrictFlexArraysLevel; } void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits