================ @@ -743,28 +808,81 @@ static bool hasUnsafeFormatOrSArg(const CallExpr *Call, const Expr *&UnsafeArg, const CallExpr *Call; unsigned FmtArgIdx; const Expr *&UnsafeArg; + ASTContext &Ctx; + + // Returns an `Expr` representing the precision if specified, null + // otherwise: + const Expr * + getPrecisionAsExpr(const analyze_printf::OptionalAmount &Precision, + const CallExpr *Call) { + unsigned PArgIdx = -1; + + if (Precision.hasDataArgument()) + PArgIdx = Precision.getPositionalArgIndex() + FmtArgIdx; + if (0 < PArgIdx && PArgIdx < Call->getNumArgs()) { + const Expr *PArg = Call->getArg(PArgIdx); + + // Strip the cast if `PArg` is a cast-to-int expression: + if (auto *CE = dyn_cast<CastExpr>(PArg); + CE && CE->getType()->isSignedIntegerType()) + PArg = CE->getSubExpr(); + return PArg; + } + if (Precision.getHowSpecified() == + analyze_printf::OptionalAmount::HowSpecified::Constant) { + auto SizeTy = Ctx.getSizeType(); + llvm::APSInt PArgVal = llvm::APSInt( + llvm::APInt(Ctx.getTypeSize(SizeTy), Precision.getConstantAmount()), + true); + + return IntegerLiteral::Create(Ctx, PArgVal, Ctx.getSizeType(), {}); + } + return nullptr; + } public: StringFormatStringHandler(const CallExpr *Call, unsigned FmtArgIdx, - const Expr *&UnsafeArg) - : Call(Call), FmtArgIdx(FmtArgIdx), UnsafeArg(UnsafeArg) {} + const Expr *&UnsafeArg, ASTContext &Ctx) + : Call(Call), FmtArgIdx(FmtArgIdx), UnsafeArg(UnsafeArg), Ctx(Ctx) {} bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen, const TargetInfo &Target) override { - if (FS.getConversionSpecifier().getKind() == - analyze_printf::PrintfConversionSpecifier::sArg) { - unsigned ArgIdx = FS.getPositionalArgIndex() + FmtArgIdx; - - if (0 < ArgIdx && ArgIdx < Call->getNumArgs()) - if (!isNullTermPointer(Call->getArg(ArgIdx))) { - UnsafeArg = Call->getArg(ArgIdx); // output - // returning false stops parsing immediately - return false; - } - } - return true; // continue parsing + if (FS.getConversionSpecifier().getKind() != + analyze_printf::PrintfConversionSpecifier::sArg) + return true; // continue parsing + + unsigned ArgIdx = FS.getPositionalArgIndex() + FmtArgIdx; + + if (!(0 < ArgIdx && ArgIdx < Call->getNumArgs())) + // If the `ArgIdx` is invalid, give up. + return true; // continue parsing + + const Expr *Arg = Call->getArg(ArgIdx); + + if (isNullTermPointer(Arg)) + // If Arg is a null-terminated pointer, it is safe anyway. + return true; // continue parsing + + // Otherwise, check if the specifier has a precision and if the character + // pointer is safely bound by the precision: + auto LengthModifier = FS.getLengthModifier(); + QualType ArgType = Arg->getType(); + bool IsArgTypeValid = // Is ArgType a character pointer type? + ArgType->isPointerType() && + (LengthModifier.getKind() == LengthModifier.AsWideChar + ? ArgType->getPointeeType()->isWideCharType() + : ArgType->getPointeeType()->isCharType()); + + ArgType.dump(); + if (auto *Precision = getPrecisionAsExpr(FS.getPrecision(), Call); ---------------- ziqingluo-90 wrote:
I learned this from an upstream reviewer, so I think it conforms to LLVM's coding style. https://github.com/llvm/llvm-project/pull/145862 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits