Author: Ziqing Luo Date: 2025-04-24T17:03:06-07:00 New Revision: be48c0df77413a237565a339c9ccc275b8256631
URL: https://github.com/llvm/llvm-project/commit/be48c0df77413a237565a339c9ccc275b8256631 DIFF: https://github.com/llvm/llvm-project/commit/be48c0df77413a237565a339c9ccc275b8256631.diff LOG: [-Wunsafe-buffer-usage] Fix a bug that wrongly assumed CXXMethodDecl always has an identifier (#137248) Fix a bug in UnsafeBufferUsage.cpp that wrongly assumed that CXXMethodDecl always has an identifier. rdar://149071318 Added: clang/test/SemaCXX/bug149071318.cpp Modified: clang/lib/Analysis/UnsafeBufferUsage.cpp Removed: ################################################################################ diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index 4eaf8ba61eaec..5b72382ca9772 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -675,7 +675,7 @@ static bool isNullTermPointer(const Expr *Ptr) { const CXXMethodDecl *MD = MCE->getMethodDecl(); const CXXRecordDecl *RD = MCE->getRecordDecl()->getCanonicalDecl(); - if (MD && RD && RD->isInStdNamespace()) + if (MD && RD && RD->isInStdNamespace() && MD->getIdentifier()) if (MD->getName() == "c_str" && RD->getName() == "basic_string") return true; } diff --git a/clang/test/SemaCXX/bug149071318.cpp b/clang/test/SemaCXX/bug149071318.cpp new file mode 100644 index 0000000000000..596d0e238dfba --- /dev/null +++ b/clang/test/SemaCXX/bug149071318.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage \ +// RUN: -verify %s + +// This example uncovered a bug in UnsafeBufferUsage.cpp, where the +// code assumed that a CXXMethodDecl always have an identifier. + +int printf( const char* format, char *); // <-- Fake decl of `printf`; to reproduce the bug, this example needs an implicit cast within a printf call. + +namespace std { // fake std namespace; to reproduce the bug, a CXXConversionDecl needs to be in std namespace. + class X { + char * p; + public: + operator char*() {return p;} + }; + + class Y { + public: + X x; + }; + +} + +void test(std::Y &y) { + // Here `y.x` involves an implicit cast and calls the overloaded cast operator, which has no identifier: + printf("%s", y.x); // expected-warning{{function 'printf' is unsafe}} expected-note{{}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits