|
52 | 52 | #include "llvm/ADT/SmallString.h"
|
53 | 53 | #include "llvm/ADT/StringExtras.h"
|
54 | 54 |
|
| 55 | +#include "Yaml.h" |
| 56 | +#include "llvm/Support/YAMLTraits.h" |
| 57 | + |
55 | 58 | #include <string>
|
56 | 59 |
|
57 | 60 | using namespace clang;
|
58 | 61 | using namespace clang::ento;
|
59 | 62 |
|
| 63 | + |
| 64 | + |
| 65 | +//SUMMARY CONFIGURATION PARSING |
| 66 | + |
| 67 | + |
| 68 | +struct SummaryConfiguration{ |
| 69 | + enum class ArgConstraintType{ |
| 70 | + NotNull, |
| 71 | + BufferSize |
| 72 | + }; |
| 73 | + struct ArgConstraint{ |
| 74 | + ArgConstraintType type; |
| 75 | + int arg; //Arg count in case of NotNull constraint type |
| 76 | + int bufferArg; // Arg count of the destination buffer |
| 77 | + int sizeArg; //arg count of the size argument |
| 78 | + int countArg; //arg count of the element count argument |
| 79 | + }; |
| 80 | + struct Signature{ |
| 81 | + std::vector<std::string> argTypes; |
| 82 | + std::string returnType; |
| 83 | + }; |
| 84 | + enum class EvaluationType{ |
| 85 | + NoEvalCall, |
| 86 | + EvalCallAsPure |
| 87 | + }; |
| 88 | + struct Summary{ |
| 89 | + std::string name; |
| 90 | + EvaluationType evaluationType; |
| 91 | + Signature signature; |
| 92 | + std::vector<ArgConstraint> argConstraints; |
| 93 | + |
| 94 | + }; |
| 95 | + std::vector<Summary> summaries; |
| 96 | +}; |
| 97 | + |
| 98 | +LLVM_YAML_IS_SEQUENCE_VECTOR(SummaryConfiguration::Summary) |
| 99 | +LLVM_YAML_IS_SEQUENCE_VECTOR(SummaryConfiguration::ArgConstraint) |
| 100 | + |
| 101 | +// YAML CONFIG PARSING |
| 102 | +namespace llvm { |
| 103 | +namespace yaml { |
| 104 | +template <> struct MappingTraits<SummaryConfiguration> { |
| 105 | + static void mapping(IO &IO, SummaryConfiguration &Config) { |
| 106 | + IO.mapRequired("Summaries", Config.summaries); |
| 107 | + } |
| 108 | +}; |
| 109 | +template <> struct MappingTraits<SummaryConfiguration::Summary> { |
| 110 | + static void mapping(IO &IO, SummaryConfiguration::Summary &Config) { |
| 111 | + IO.mapRequired("Name", Config.name); |
| 112 | + IO.mapRequired("EvaluationType", Config.evaluationType); |
| 113 | + IO.mapRequired("Signature", Config.signature); |
| 114 | + IO.mapRequired("ArgConstraints", Config.argConstraints); |
| 115 | + } |
| 116 | +}; |
| 117 | +template <> struct ScalarEnumerationTraits<SummaryConfiguration::EvaluationType> { |
| 118 | + static void enumeration(IO &IO, SummaryConfiguration::EvaluationType &Config) { |
| 119 | + IO.enumCase(Config, "NoEvalCall", SummaryConfiguration::EvaluationType::NoEvalCall); |
| 120 | + IO.enumCase(Config, "EvalCallAsPure", SummaryConfiguration::EvaluationType::EvalCallAsPure); |
| 121 | + } |
| 122 | +}; |
| 123 | +template <> struct MappingTraits<SummaryConfiguration::Signature> { |
| 124 | + static void mapping(IO &IO, SummaryConfiguration::Signature &Config) { |
| 125 | + IO.mapRequired("ArgTypes", Config.argTypes); |
| 126 | + IO.mapRequired("RetType", Config.returnType); |
| 127 | + } |
| 128 | +}; |
| 129 | + |
| 130 | +template <> struct ScalarEnumerationTraits<SummaryConfiguration::ArgConstraintType> { |
| 131 | + static void enumeration(IO &IO, SummaryConfiguration::ArgConstraintType &Config) { |
| 132 | + IO.enumCase(Config, "NotNull", SummaryConfiguration::ArgConstraintType::NotNull); |
| 133 | + IO.enumCase(Config, "BufferSize", SummaryConfiguration::ArgConstraintType::BufferSize); |
| 134 | + } |
| 135 | +}; |
| 136 | + |
| 137 | +template <> struct MappingTraits<SummaryConfiguration::ArgConstraint> { |
| 138 | + static void mapping(IO &IO, SummaryConfiguration::ArgConstraint &Config) { |
| 139 | + IO.mapRequired("type", Config.type); |
| 140 | + IO.mapOptional("arg", Config.arg); |
| 141 | + IO.mapOptional("bufferArg", Config.bufferArg); |
| 142 | + IO.mapOptional("sizeArg", Config.sizeArg); |
| 143 | + IO.mapOptional("countArg", Config.countArg); |
| 144 | + } |
| 145 | +}; |
| 146 | + |
| 147 | +} // namespace yaml |
| 148 | +} // namespace llvm |
| 149 | + |
| 150 | + |
60 | 151 | namespace {
|
61 | 152 | class StdLibraryFunctionsChecker
|
62 | 153 | : public Checker<check::PreCall, check::PostCall, eval::Call> {
|
@@ -1357,6 +1448,84 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
|
1357 | 1448 | Optional<QualType> FilePtrTy = getPointerTy(FileTy);
|
1358 | 1449 | Optional<QualType> FilePtrRestrictTy = getRestrictTy(FilePtrTy);
|
1359 | 1450 |
|
| 1451 | +////////READING SUMMARY CONFIG///////////////////// |
| 1452 | + |
| 1453 | +// User-provided summary configuration. |
| 1454 | +CheckerManager *Mgr = C.getAnalysisManager().getCheckerManager(); |
| 1455 | +std::string Option{"Config"}; |
| 1456 | +/*StringRef ConfigFile = |
| 1457 | + Mgr->getAnalyzerOptions().getCheckerStringOption(this, Option);*/ |
| 1458 | +StringRef ConfigFile = "/local/workspace/llvm-project/clang/test/Analysis/Inputs/fread-summary.yaml"; |
| 1459 | +llvm::Optional<SummaryConfiguration> Config = |
| 1460 | + getConfiguration<SummaryConfiguration>(*Mgr, this, Option, ConfigFile); |
| 1461 | +llvm::errs()<<"Config :"<<Config.hasValue()<<"\n"; |
| 1462 | +if (Config.has_value()){ |
| 1463 | + for (const SummaryConfiguration::Summary &s : Config->summaries){ |
| 1464 | + llvm::errs()<<"Config :"<<s.name<<"\n"; |
| 1465 | + |
| 1466 | + ArgTypes args; |
| 1467 | + for (const std::string &t: s.signature.argTypes){ |
| 1468 | + auto ltype = lookupTy(t); |
| 1469 | + if (ltype.has_value()){ |
| 1470 | + llvm::errs()<<"type string:"<<t<<"\n"; |
| 1471 | + ltype->dump(); |
| 1472 | + args.push_back(lookupTy(t)); |
| 1473 | + } |
| 1474 | + } |
| 1475 | + RetType rt = lookupTy(s.signature.returnType); |
| 1476 | + auto GetSummary = [s]() { |
| 1477 | + switch (s.evaluationType) { |
| 1478 | + case SummaryConfiguration::EvaluationType::NoEvalCall: |
| 1479 | + return Summary(NoEvalCall); |
| 1480 | + case SummaryConfiguration::EvaluationType::EvalCallAsPure: |
| 1481 | + return Summary(EvalCallAsPure); |
| 1482 | + } |
| 1483 | + }; |
| 1484 | + Summary summary = GetSummary(); |
| 1485 | + |
| 1486 | + for (const SummaryConfiguration::ArgConstraint &ac: s.argConstraints){ |
| 1487 | + switch (ac.type){ |
| 1488 | + case SummaryConfiguration::ArgConstraintType::NotNull: |
| 1489 | + summary.ArgConstraint(NotNull(ac.arg)); |
| 1490 | + break; |
| 1491 | + case SummaryConfiguration::ArgConstraintType::BufferSize: |
| 1492 | + summary.ArgConstraint(BufferSize(ac.bufferArg,ac.sizeArg, ac.countArg)); |
| 1493 | + break; |
| 1494 | + } |
| 1495 | + } |
| 1496 | + |
| 1497 | + addToFunctionSummaryMap( |
| 1498 | + s.name, |
| 1499 | + Signature(args, |
| 1500 | + rt), |
| 1501 | + summary); |
| 1502 | + } |
| 1503 | +} |
| 1504 | + /* |
| 1505 | + WE want to add this |
| 1506 | + auto FreadSummary = |
| 1507 | + Summary(NoEvalCall) |
| 1508 | + .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), |
| 1509 | + ReturnValueCondition(WithinRange, Range(0, SizeMax))}, |
| 1510 | + ErrnoIrrelevant) |
| 1511 | + .ArgConstraint(NotNull(ArgNo(0))) |
| 1512 | + .ArgConstraint(NotNull(ArgNo(3))) |
| 1513 | + .ArgConstraint(BufferSize(ArgNo(0), ArgNo(1), |
| 1514 | + ArgNo(2))); |
| 1515 | + */ |
| 1516 | + // size_t fread(void *restrict ptr, size_t size, size_t nitems, |
| 1517 | + // FILE *restrict stream); |
| 1518 | + /*addToFunctionSummaryMap( |
| 1519 | + "fread", |
| 1520 | + Signature(ArgTypes{VoidPtrRestrictTy, SizeTy, SizeTy, FilePtrRestrictTy}, |
| 1521 | + RetType{SizeTy}), |
| 1522 | + FreadSummary);*/ |
| 1523 | + |
| 1524 | + |
| 1525 | +//////////////////////////////////////////////////// |
| 1526 | + |
| 1527 | + |
| 1528 | + |
1360 | 1529 | // We are finally ready to define specifications for all supported functions.
|
1361 | 1530 | //
|
1362 | 1531 | // Argument ranges should always cover all variants. If return value
|
@@ -1591,11 +1760,11 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
|
1591 | 1760 |
|
1592 | 1761 | // size_t fread(void *restrict ptr, size_t size, size_t nitems,
|
1593 | 1762 | // FILE *restrict stream);
|
1594 |
| - addToFunctionSummaryMap( |
| 1763 | + /*addToFunctionSummaryMap( |
1595 | 1764 | "fread",
|
1596 | 1765 | Signature(ArgTypes{VoidPtrRestrictTy, SizeTy, SizeTy, FilePtrRestrictTy},
|
1597 | 1766 | RetType{SizeTy}),
|
1598 |
| - FreadSummary); |
| 1767 | + FreadSummary);*/ |
1599 | 1768 | // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems,
|
1600 | 1769 | // FILE *restrict stream);
|
1601 | 1770 | addToFunctionSummaryMap("fwrite",
|
@@ -3015,3 +3184,4 @@ bool ento::shouldRegisterStdCLibraryFunctionsChecker(
|
3015 | 3184 |
|
3016 | 3185 | REGISTER_CHECKER(StdCLibraryFunctionArgsChecker)
|
3017 | 3186 | REGISTER_CHECKER(StdCLibraryFunctionsTesterChecker)
|
| 3187 | + |
0 commit comments