Skip to content
1 change: 1 addition & 0 deletions clang/include/clang/AST/RandstructSeed.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
#include <string>
namespace clang {
extern std::string RandstructSeed;
extern bool RandstructAutoSelect;
}
#endif
3 changes: 3 additions & 0 deletions clang/include/clang/AST/RecordFieldReorganizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Decl *, 64> &NewOrder) const override;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1751,6 +1751,9 @@ def freroll_loops : Flag<["-"], "freroll-loops">, Group<f_Group>,
HelpText<"Turn on loop reroller">, Flags<[CC1Option]>;
def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group<f_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<f_Group>,
HelpText<"Process trigraph sequences">, Flags<[CC1Option]>;
def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
Expand Down
12 changes: 9 additions & 3 deletions clang/lib/AST/RecordFieldReorganizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

namespace clang {
std::string RandstructSeed = "";
bool RandstructAutoSelect = false;

void RecordFieldReorganizer::reorganizeFields(const ASTContext &C,
const RecordDecl *D) const {
Expand All @@ -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);

Expand All @@ -52,7 +52,6 @@ void RecordFieldReorganizer::reorganizeFields(const ASTContext &C,

commit(D, fields);
}

void RecordFieldReorganizer::commit(
const RecordDecl *D, SmallVectorImpl<Decl *> &NewFieldOrder) const {
Decl *First, *Last;
Expand Down Expand Up @@ -254,5 +253,12 @@ void Randstruct::reorganize(const ASTContext &C, const RecordDecl *D,
SmallVector<Decl *, 64> 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
4 changes: 2 additions & 2 deletions clang/lib/AST/RecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2987,8 +2987,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
if (Entry) return *Entry;

const ASTRecordLayout *NewEntry = nullptr;
bool ShouldBeRandomized = D->getAttr<RandomizeLayoutAttr>() != nullptr;

bool ShouldBeRandomized = (RandstructAutoSelect && Randstruct::isTriviallyRandomizable(D)) || D->getAttr<RandomizeLayoutAttr>() != nullptr;
if (ShouldBeRandomized) {
// There is no technical benefit to randomizing the fields of a union
// since they all share the same offset of zero.
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down