diff --git a/clang/include/clang/AST/RandstructSeed.h b/clang/include/clang/AST/RandstructSeed.h index 483dda27b14e5..eefdd8916f4b6 100644 --- a/clang/include/clang/AST/RandstructSeed.h +++ b/clang/include/clang/AST/RandstructSeed.h @@ -3,5 +3,6 @@ #include namespace clang { extern std::string RandstructSeed; +extern bool RandstructAutoSelect; } #endif diff --git a/clang/include/clang/AST/RecordFieldReorganizer.h b/clang/include/clang/AST/RecordFieldReorganizer.h index 1f2562b5e389c..9f65d85a63dbe 100644 --- a/clang/include/clang/AST/RecordFieldReorganizer.h +++ b/clang/include/clang/AST/RecordFieldReorganizer.h @@ -37,6 +37,9 @@ class RecordFieldReorganizer { }; class Randstruct : public RecordFieldReorganizer { +public: +/// Determines if the Record can be safely and easily randomized based on certain criteria (see implementation). + static bool isTriviallyRandomizable(const RecordDecl *D); protected: virtual void reorganize(const ASTContext &C, const RecordDecl *D, SmallVector &NewOrder) const override; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index b86c776e829e4..edf714adbf936 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1751,6 +1751,9 @@ def freroll_loops : Flag<["-"], "freroll-loops">, Group, HelpText<"Turn on loop reroller">, Flags<[CC1Option]>; def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group, HelpText<"Turn off loop reroller">; +def randstruct_auto : Flag<["-"], "randstruct-auto">, + HelpText<"Enable automatic structure selection for field randomization; " + "Disable for specific structures with attribute no_randomize_layout">, Flags<[CC1Option]>; def ftrigraphs : Flag<["-"], "ftrigraphs">, Group, HelpText<"Process trigraph sequences">, Flags<[CC1Option]>; def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group, diff --git a/clang/lib/AST/RecordFieldReorganizer.cpp b/clang/lib/AST/RecordFieldReorganizer.cpp index 52bda0dabff8b..91783fd7cd415 100644 --- a/clang/lib/AST/RecordFieldReorganizer.cpp +++ b/clang/lib/AST/RecordFieldReorganizer.cpp @@ -25,6 +25,7 @@ namespace clang { std::string RandstructSeed = ""; +bool RandstructAutoSelect = false; void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, const RecordDecl *D) const { @@ -37,7 +38,6 @@ void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, mutateGuard.insert(f); fields.push_back(f); } - // Now allow subclass implementations to reorder the fields reorganize(C, D, fields); @@ -52,7 +52,6 @@ void RecordFieldReorganizer::reorganizeFields(const ASTContext &C, commit(D, fields); } - void RecordFieldReorganizer::commit( const RecordDecl *D, SmallVectorImpl &NewFieldOrder) const { Decl *First, *Last; @@ -254,5 +253,12 @@ void Randstruct::reorganize(const ASTContext &C, const RecordDecl *D, SmallVector randomized = perfrandomize(C, NewOrder); NewOrder = randomized; } - +bool Randstruct::isTriviallyRandomizable(const RecordDecl *D) { + for (auto f : D->fields()){ + //If an element of the structure does not have a + //function type is not a function pointer + if(f->getFunctionType() == nullptr){ return false; } + } + return true; +} } // namespace clang diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 11f96294fdc53..bb100b48bedc1 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2987,8 +2987,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { if (Entry) return *Entry; const ASTRecordLayout *NewEntry = nullptr; - - bool ShouldBeRandomized = D->getAttr() != nullptr; + + bool ShouldBeRandomized = (RandstructAutoSelect && Randstruct::isTriviallyRandomizable(D)) || D->getAttr() != nullptr; if (ShouldBeRandomized) { // There is no technical benefit to randomizing the fields of a union // since they all share the same offset of zero. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index ea62b79570704..7edade7c758bf 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4411,6 +4411,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(0)); } + if (Arg *A = Args.getLastArg(options::OPT_randstruct_auto)) { + CmdArgs.push_back( "-randstruct-auto" ); + } + // -fvisibility= and -fvisibility-ms-compat are of a piece. if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ, options::OPT_fvisibility_ms_compat)) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index cd08ac5847b3b..312c95d8b18b9 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1674,6 +1674,9 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, if (const Arg* A = Args.getLastArg(OPT_randstruct_seed)) { RandstructSeed = A->getValue(0); } + if (const Arg* A = Args.getLastArg(OPT_randstruct_auto)) { + RandstructAutoSelect = true; + } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); for (const auto *AA : Args.filtered(OPT_plugin_arg)) Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));