-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[Clang] Added clang diagnostic when snprintf/vsnprintf uses sizeof(de… #170637
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1139,6 +1139,37 @@ static bool ProcessFormatStringLiteral(const Expr *FormatExpr, | |
| return false; | ||
| } | ||
|
|
||
| static const UnaryExprOrTypeTraitExpr *getAsSizeOfExpr(const Expr *E) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should avoid this large code movement, we could forward declare these functions instead, but I think a better approach be to move the actual diagnosis logic into a separate function. |
||
| if (const auto *Unary = dyn_cast<UnaryExprOrTypeTraitExpr>(E)) | ||
| if (Unary->getKind() == UETT_SizeOf) | ||
| return Unary; | ||
| return nullptr; | ||
| } | ||
|
|
||
| /// If E is a sizeof expression, returns its argument expression, | ||
| /// otherwise returns NULL. | ||
| static const Expr *getSizeOfExprArg(const Expr *E) { | ||
| if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E)) | ||
| if (!SizeOf->isArgumentType()) | ||
| return SizeOf->getArgumentExpr()->IgnoreParenImpCasts(); | ||
| return nullptr; | ||
| } | ||
|
|
||
| /// If E is a sizeof expression, returns its argument type. | ||
| static QualType getSizeOfArgType(const Expr *E) { | ||
| if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E)) | ||
| return SizeOf->getTypeOfArgument(); | ||
| return QualType(); | ||
| } | ||
|
|
||
| /// Check if two expressions refer to the same declaration. | ||
| static bool referToTheSameDecl(const Expr *E1, const Expr *E2) { | ||
| if (const DeclRefExpr *D1 = dyn_cast_or_null<DeclRefExpr>(E1)) | ||
| if (const DeclRefExpr *D2 = dyn_cast_or_null<DeclRefExpr>(E2)) | ||
| return D1->getDecl() == D2->getDecl(); | ||
| return false; | ||
| } | ||
|
|
||
| void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, | ||
| CallExpr *TheCall) { | ||
| if (TheCall->isValueDependent() || TheCall->isTypeDependent() || | ||
|
|
@@ -1449,6 +1480,17 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, | |
| } | ||
| } | ||
| DestinationSize = ComputeSizeArgument(0); | ||
| const Expr *SizeOfArg = TheCall->getArg(1)->IgnoreParenImpCasts(); | ||
| const Expr *Dest = TheCall->getArg(0)->IgnoreParenImpCasts(); | ||
| const Expr *SizeOfArgExpr = getSizeOfExprArg(SizeOfArg); | ||
| const QualType SizeOfArgType = getSizeOfArgType(SizeOfArg); | ||
| const Type *ExprType = SizeOfArgType.getTypePtrOrNull(); | ||
| if (ExprType && ExprType->isPointerType() && | ||
| referToTheSameDecl(SizeOfArgExpr, Dest)) { | ||
| DiagRuntimeBehavior(SizeOfArg->getExprLoc(), Dest, | ||
| PDiag(diag::warn_sizeof_pointer_dest_type_memacess) | ||
| << FD->getNameInfo().getName()); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than a reimplementation of similar semantics we should consider refactoring the existing checks so they can be used here instead. |
||
| } | ||
| } | ||
|
|
||
|
|
@@ -9979,29 +10021,6 @@ static const CXXRecordDecl *getContainedDynamicClass(QualType T, | |
| return nullptr; | ||
| } | ||
|
|
||
| static const UnaryExprOrTypeTraitExpr *getAsSizeOfExpr(const Expr *E) { | ||
| if (const auto *Unary = dyn_cast<UnaryExprOrTypeTraitExpr>(E)) | ||
| if (Unary->getKind() == UETT_SizeOf) | ||
| return Unary; | ||
| return nullptr; | ||
| } | ||
|
|
||
| /// If E is a sizeof expression, returns its argument expression, | ||
| /// otherwise returns NULL. | ||
| static const Expr *getSizeOfExprArg(const Expr *E) { | ||
| if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E)) | ||
| if (!SizeOf->isArgumentType()) | ||
| return SizeOf->getArgumentExpr()->IgnoreParenImpCasts(); | ||
| return nullptr; | ||
| } | ||
|
|
||
| /// If E is a sizeof expression, returns its argument type. | ||
| static QualType getSizeOfArgType(const Expr *E) { | ||
| if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E)) | ||
| return SizeOf->getTypeOfArgument(); | ||
| return QualType(); | ||
| } | ||
|
|
||
| namespace { | ||
|
|
||
| struct SearchNonTrivialToInitializeField | ||
|
|
@@ -10499,14 +10518,6 @@ void Sema::CheckStrlcpycatArguments(const CallExpr *Call, | |
| OS.str()); | ||
| } | ||
|
|
||
| /// Check if two expressions refer to the same declaration. | ||
| static bool referToTheSameDecl(const Expr *E1, const Expr *E2) { | ||
| if (const DeclRefExpr *D1 = dyn_cast_or_null<DeclRefExpr>(E1)) | ||
| if (const DeclRefExpr *D2 = dyn_cast_or_null<DeclRefExpr>(E2)) | ||
| return D1->getDecl() == D2->getDecl(); | ||
| return false; | ||
| } | ||
|
|
||
| static const Expr *getStrlenExprArg(const Expr *E) { | ||
| if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { | ||
| const FunctionDecl *FD = CE->getDirectCallee(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should reuse warn_sizeof_pointer_type_memaccess and the associated note.