void created this revision.
void added reviewers: aaron.ballman, MaskRay.
Herald added a subscriber: StephenFan.
Herald added a project: All.
void requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This test makes sure that the "-frandomize-layout-seed" and
"-frandomize-layout-seed-file" flags generate the same layout for the
record.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D123636

Files:
  clang/unittests/AST/RandstructTest.cpp

Index: clang/unittests/AST/RandstructTest.cpp
===================================================================
--- clang/unittests/AST/RandstructTest.cpp
+++ clang/unittests/AST/RandstructTest.cpp
@@ -27,6 +27,7 @@
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Testing/CommandLineArgs.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/Support/ToolOutputFile.h"
 
 #include <vector>
 
@@ -36,18 +37,40 @@
 
 using field_names = std::vector<std::string>;
 
-static std::unique_ptr<ASTUnit> makeAST(const std::string &SourceCode) {
+static std::string Seed = "1234567890abcdef";
+
+static auto makeAST = [](const std::string &SourceCode) {
   std::vector<std::string> Args = getCommandLineArgsForTesting(Lang_C99);
-  Args.push_back("-frandomize-layout-seed=1234567890abcdef");
+  Args.push_back("-frandomize-layout-seed=" + Seed);
 
   IgnoringDiagConsumer IgnoringConsumer = IgnoringDiagConsumer();
 
-  return tooling::buildASTFromCodeWithArgs(
+  std::unique_ptr<ASTUnit> AST = tooling::buildASTFromCodeWithArgs(
       SourceCode, Args, "input.c", "clang-tool",
       std::make_shared<PCHContainerOperations>(),
       tooling::getClangStripDependencyFileAdjuster(),
       tooling::FileContentMappings(), &IgnoringConsumer);
-}
+
+  int SeedFileFD = -1;
+  llvm::SmallString<256> SeedFilename;
+  EXPECT_FALSE(llvm::sys::fs::createTemporaryFile("seed", "rng", SeedFileFD,
+                                                  SeedFilename));
+  llvm::ToolOutputFile SeedFile(SeedFilename, SeedFileFD);
+  SeedFile.os() << Seed << "\n";
+
+  Args.clear();
+  Args = getCommandLineArgsForTesting(Lang_C99);
+  Args.push_back("-frandomize-layout-seed-file=" +
+                 SeedFile.getFilename().str());
+
+  std::unique_ptr<ASTUnit> ASTFileSeed = tooling::buildASTFromCodeWithArgs(
+      SourceCode, Args, "input.c", "clang-tool",
+      std::make_shared<PCHContainerOperations>(),
+      tooling::getClangStripDependencyFileAdjuster(),
+      tooling::FileContentMappings(), &IgnoringConsumer);
+
+  return std::tuple<ASTUnit *, ASTUnit *>(AST.release(), ASTFileSeed.release());
+};
 
 static RecordDecl *getRecordDeclFromAST(const ASTContext &C,
                                         const std::string &Name) {
@@ -85,6 +108,19 @@
   return IsSubseq;
 }
 
+static bool recordsEqual(const ASTUnit *LHS, const ASTUnit *RHS,
+                         std::string RecordName) {
+  const RecordDecl *LHSRD =
+      getRecordDeclFromAST(LHS->getASTContext(), RecordName);
+  const RecordDecl *RHSRD =
+      getRecordDeclFromAST(LHS->getASTContext(), RecordName);
+
+  std::vector<std::string> LHSFields = getFieldNamesFromRecord(LHSRD);
+  std::vector<std::string> RHSFields = getFieldNamesFromRecord(RHSRD);
+
+  return LHSFields == RHSFields;
+}
+
 namespace clang {
 namespace ast_matchers {
 
@@ -103,7 +139,8 @@
 #define RANDSTRUCT_TEST StructureLayoutRandomization
 
 TEST(RANDSTRUCT_TEST, UnmarkedStruct) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     struct test {
         int bacon;
         long lettuce;
@@ -118,10 +155,13 @@
 
   EXPECT_FALSE(RD->hasAttr<RandomizeLayoutAttr>());
   EXPECT_FALSE(RD->isRandomized());
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, MarkedNoRandomize) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     struct test {
         int bacon;
         long lettuce;
@@ -134,12 +174,16 @@
 
   const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test");
 
+  EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "test"));
   EXPECT_TRUE(RD->hasAttr<NoRandomizeLayoutAttr>());
   EXPECT_FALSE(RD->isRandomized());
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, MarkedRandomize) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     struct test {
         int bacon;
         long lettuce;
@@ -152,12 +196,16 @@
 
   const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test");
 
+  EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "test"));
   EXPECT_TRUE(RD->hasAttr<RandomizeLayoutAttr>());
   EXPECT_TRUE(RD->isRandomized());
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, MismatchedAttrsDeclVsDef) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     struct test __attribute__((randomize_layout));
     struct test {
         int bacon;
@@ -169,18 +217,21 @@
 
   EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred());
 
-  DiagnosticsEngine &Diags = AST->getDiagnostics();
+  const DiagnosticsEngine &Diags = AST->getDiagnostics();
 
   EXPECT_FALSE(Diags.hasFatalErrorOccurred());
   EXPECT_FALSE(Diags.hasUncompilableErrorOccurred());
   EXPECT_FALSE(Diags.hasUnrecoverableErrorOccurred());
   EXPECT_EQ(Diags.getNumWarnings(), 1u);
   EXPECT_EQ(Diags.getNumErrors(), 0u);
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, MismatchedAttrsRandomizeVsNoRandomize) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
-    struct test2 {
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
+    struct test {
         int bacon;
         long lettuce;
         long long tomato;
@@ -190,16 +241,19 @@
 
   EXPECT_TRUE(AST->getDiagnostics().hasErrorOccurred());
 
-  DiagnosticsEngine &Diags = AST->getDiagnostics();
+  const DiagnosticsEngine &Diags = AST->getDiagnostics();
 
   EXPECT_TRUE(Diags.hasUncompilableErrorOccurred());
   EXPECT_TRUE(Diags.hasUnrecoverableErrorOccurred());
   EXPECT_EQ(Diags.getNumWarnings(), 0u);
   EXPECT_EQ(Diags.getNumErrors(), 1u);
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, MismatchedAttrsNoRandomizeVsRandomize) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     struct test3 {
         int bacon;
         long lettuce;
@@ -210,16 +264,19 @@
 
   EXPECT_TRUE(AST->getDiagnostics().hasErrorOccurred());
 
-  DiagnosticsEngine &Diags = AST->getDiagnostics();
+  const DiagnosticsEngine &Diags = AST->getDiagnostics();
 
   EXPECT_TRUE(Diags.hasUncompilableErrorOccurred());
   EXPECT_TRUE(Diags.hasUnrecoverableErrorOccurred());
   EXPECT_EQ(Diags.getNumWarnings(), 0u);
   EXPECT_EQ(Diags.getNumErrors(), 1u);
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, CheckAdjacentBitfieldsRemainAdjacentAfterRandomization) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     struct test {
         int a;
         int b;
@@ -236,12 +293,16 @@
   const field_names Actual = getFieldNamesFromRecord(RD);
   const field_names Subseq = {"x", "y", "z"};
 
+  EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "test"));
   EXPECT_TRUE(RD->isRandomized());
   EXPECT_TRUE(isSubsequence(Actual, Subseq));
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, CheckVariableLengthArrayMemberRemainsAtEndOfStructure) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     struct test {
         int a;
         double b;
@@ -254,11 +315,15 @@
 
   const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test");
 
+  EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "test"));
   EXPECT_TRUE(RD->isRandomized());
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, RandstructDoesNotOverrideThePackedAttr) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     struct test_struct {
         char a;
         float b[3];
@@ -290,6 +355,7 @@
     const ASTRecordLayout *Layout =
         &AST->getASTContext().getASTRecordLayout(RD);
 
+    EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "test_struct"));
     EXPECT_TRUE(RD->isRandomized());
     EXPECT_EQ(19, Layout->getSize().getQuantity());
   }
@@ -300,6 +366,7 @@
     const ASTRecordLayout *Layout =
         &AST->getASTContext().getASTRecordLayout(RD);
 
+    EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "another_struct"));
     EXPECT_TRUE(RD->isRandomized());
     EXPECT_EQ(10, Layout->getSize().getQuantity());
   }
@@ -310,13 +377,18 @@
     const ASTRecordLayout *Layout =
         &AST->getASTContext().getASTRecordLayout(RD);
 
+    EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "last_struct"));
     EXPECT_TRUE(RD->isRandomized());
     EXPECT_EQ(9, Layout->getSize().getQuantity());
   }
+
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, ZeroWidthBitfieldsSeparateAllocationUnits) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     struct test {
         int a : 1;
         int   : 0;
@@ -328,11 +400,15 @@
 
   const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test");
 
+  EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "test"));
   EXPECT_TRUE(RD->isRandomized());
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, RandstructDoesNotRandomizeUnionFieldOrder) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     union test_union {
         int a;
         int b;
@@ -348,11 +424,15 @@
   const RecordDecl *RD =
       getRecordDeclFromAST(AST->getASTContext(), "test_union");
 
+  EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "test_union"));
   EXPECT_FALSE(RD->isRandomized());
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, AnonymousStructsAndUnionsRetainFieldOrder) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     struct test_struct {
         int a;
         struct sub_struct {
@@ -387,6 +467,7 @@
   const RecordDecl *RD =
       getRecordDeclFromAST(AST->getASTContext(), "test_struct");
 
+  EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "test_struct"));
   EXPECT_TRUE(RD->isRandomized());
 
   bool AnonStructTested = false;
@@ -415,10 +496,13 @@
 
   EXPECT_TRUE(AnonStructTested);
   EXPECT_TRUE(AnonUnionTested);
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, AutoRandomizeStructOfFunctionPointers) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     typedef void (*func_ptr)();
 
     struct test {
@@ -436,11 +520,15 @@
 
   const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test");
 
+  EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "test"));
   EXPECT_TRUE(RD->isRandomized());
+  delete AST;
+  delete ASTFileSeed;
 }
 
 TEST(RANDSTRUCT_TEST, DisableAutoRandomizeStructOfFunctionPointers) {
-  const std::unique_ptr<ASTUnit> AST = makeAST(R"c(
+  const ASTUnit *AST, *ASTFileSeed;
+  std::tie(AST, ASTFileSeed) = makeAST(R"c(
     typedef void (*func_ptr)();
 
     struct test {
@@ -458,7 +546,10 @@
 
   const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test");
 
+  EXPECT_TRUE(recordsEqual(AST, ASTFileSeed, "test"));
   EXPECT_FALSE(RD->isRandomized());
+  delete AST;
+  delete ASTFileSeed;
 }
 
 } // namespace ast_matchers
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to