10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 12 #include "clang/AST/FormatString.h" 13 #include "llvm/ADT/StringSwitch.h" 22 void StrToNumCheck::registerMatchers(MatchFinder *Finder) {
27 callee(functionDecl(anyOf(
28 functionDecl(hasAnyName(
"::atoi",
"::atof",
"::atol",
"::atoll"))
30 functionDecl(hasAnyName(
"::scanf",
"::sscanf",
"::fscanf",
31 "::vfscanf",
"::vscanf",
"::vsscanf"))
32 .bind(
"formatted")))))
52 return llvm::StringSwitch<ConversionKind>(FD->getName())
53 .Cases(
"atoi",
"atol", ConversionKind::ToInt)
54 .Case(
"atoll", ConversionKind::ToLongInt)
55 .Case(
"atof", ConversionKind::ToDouble)
56 .Default(ConversionKind::None);
59 ConversionKind ClassifyFormatString(StringRef Fmt,
const LangOptions &LO,
60 const TargetInfo &TI) {
65 class Handler :
public analyze_format_string::FormatStringHandler {
68 bool HandleScanfSpecifier(
const analyze_scanf::ScanfSpecifier &
FS,
69 const char *startSpecifier,
70 unsigned specifierLen)
override {
73 if (!FS.consumesDataArgument())
78 analyze_scanf::ScanfConversionSpecifier SCS = FS.getConversionSpecifier();
80 switch (FS.getLengthModifier().getKind()) {
81 case analyze_scanf::LengthModifier::AsLongLong:
82 CK = ConversionKind::ToLongInt;
84 case analyze_scanf::LengthModifier::AsIntMax:
85 CK = ConversionKind::ToIntMax;
88 CK = ConversionKind::ToInt;
91 }
else if (SCS.isUIntArg()) {
92 switch (FS.getLengthModifier().getKind()) {
93 case analyze_scanf::LengthModifier::AsLongLong:
94 CK = ConversionKind::ToLongUInt;
96 case analyze_scanf::LengthModifier::AsIntMax:
97 CK = ConversionKind::ToUIntMax;
100 CK = ConversionKind::ToUInt;
103 }
else if (SCS.isDoubleArg()) {
104 switch (FS.getLengthModifier().getKind()) {
105 case analyze_scanf::LengthModifier::AsLongDouble:
106 CK = ConversionKind::ToLongDouble;
108 case analyze_scanf::LengthModifier::AsLong:
109 CK = ConversionKind::ToDouble;
112 CK = ConversionKind::ToFloat;
118 return CK == ConversionKind::None;
122 Handler() : CK(ConversionKind::None) {}
128 analyze_format_string::ParseScanfString(H, Fmt.begin(), Fmt.end(), LO, TI);
135 case ConversionKind::None:
136 llvm_unreachable(
"Unexpected conversion kind");
137 case ConversionKind::ToInt:
138 case ConversionKind::ToLongInt:
139 case ConversionKind::ToIntMax:
140 return "an integer value";
141 case ConversionKind::ToUInt:
142 case ConversionKind::ToLongUInt:
143 case ConversionKind::ToUIntMax:
144 return "an unsigned integer value";
145 case ConversionKind::ToFloat:
146 case ConversionKind::ToDouble:
147 case ConversionKind::ToLongDouble:
148 return "a floating-point value";
150 llvm_unreachable(
"Unknown conversion kind");
155 case ConversionKind::None:
156 llvm_unreachable(
"Unexpected conversion kind");
157 case ConversionKind::ToInt:
159 case ConversionKind::ToUInt:
161 case ConversionKind::ToIntMax:
163 case ConversionKind::ToLongInt:
165 case ConversionKind::ToLongUInt:
167 case ConversionKind::ToUIntMax:
169 case ConversionKind::ToFloat:
171 case ConversionKind::ToDouble:
173 case ConversionKind::ToLongDouble:
176 llvm_unreachable(
"Unknown conversion kind");
180 void StrToNumCheck::check(
const MatchFinder::MatchResult &Result) {
181 const auto *Call = Result.Nodes.getNodeAs<CallExpr>(
"expr");
182 const FunctionDecl *FuncDecl =
nullptr;
183 ConversionKind Conversion;
185 if (
const auto *ConverterFunc =
186 Result.Nodes.getNodeAs<FunctionDecl>(
"converter")) {
188 FuncDecl = ConverterFunc;
189 Conversion = ClassifyConversionFunc(ConverterFunc);
190 }
else if (
const auto *FFD =
191 Result.Nodes.getNodeAs<FunctionDecl>(
"formatted")) {
197 (FFD->getName() ==
"scanf" || FFD->getName() ==
"vscanf") ? 0 : 1;
201 if (Call->getNumArgs() < Idx)
204 if (
const Expr *Arg = Call->getArg(Idx)->IgnoreParenImpCasts()) {
205 if (
const auto *SL = dyn_cast<StringLiteral>(Arg)) {
206 FmtStr = SL->getString();
216 Conversion = ClassifyFormatString(FmtStr, getLangOpts(),
217 Result.Context->getTargetInfo());
218 if (Conversion != ConversionKind::None)
225 diag(Call->getExprLoc(),
226 "%0 used to convert a string to %1, but function will not report " 227 "conversion errors; consider using '%2' instead")
228 << FuncDecl << ClassifyConversionType(Conversion)
229 << ClassifyReplacement(Conversion);
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//