https://github.com/HendrikHuebner updated https://github.com/llvm/llvm-project/pull/91057
From 4879999ec3df346924f71b66e5753c844c97991e Mon Sep 17 00:00:00 2001 From: hhuebner <hendrik.huebne...@gmail.com> Date: Sat, 4 May 2024 13:49:38 +0200 Subject: [PATCH 1/2] [Clang] Throw error when calling atomic with pointer to zero size object --- .../clang/Basic/DiagnosticSemaKinds.td | 4 ++- clang/lib/Sema/SemaChecking.cpp | 17 +++++++--- clang/test/Sema/atomic-ops.c | 32 +++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6c4d92790afc5..4aab1d86fc5ec 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8808,8 +8808,10 @@ def err_builtin_fn_use : Error<"builtin functions must be directly called">; def warn_call_wrong_number_of_arguments : Warning< "too %select{few|many}0 arguments in call to %1">; + def err_atomic_builtin_must_be_pointer : Error< - "address argument to atomic builtin must be a pointer (%0 invalid)">; + "address argument to atomic builtin must be a pointer %select{|to a non-zero-sized object }1(%0 invalid)">; + def err_atomic_builtin_must_be_pointer_intptr : Error< "address argument to atomic builtin must be a pointer to integer or pointer" " (%0 invalid)">; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 3179d542b1f92..22ed9776f5995 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3820,7 +3820,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>(); if (!pointerType) { Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer) - << PointerArg->getType() << PointerArg->getSourceRange(); + << PointerArg->getType() << 0 << PointerArg->getSourceRange(); return true; } @@ -3854,7 +3854,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && !ValType->isBlockPointerType() && !ValType->isFloatingType()) { Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr) - << PointerArg->getType() << PointerArg->getSourceRange(); + << PointerArg->getType() << 0 << PointerArg->getSourceRange(); return true; } @@ -8526,7 +8526,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, const PointerType *pointerType = Ptr->getType()->getAs<PointerType>(); if (!pointerType) { Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer) - << Ptr->getType() << Ptr->getSourceRange(); + << Ptr->getType() << 0 << Ptr->getSourceRange(); return ExprError(); } @@ -8555,6 +8555,13 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, } } + // Pointer to object of size zero is not allowed. + if (Context.getTypeInfoInChars(AtomTy).Width.isZero()) { + Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer) + << Ptr->getType() << 1 << Ptr->getSourceRange(); + return ExprError(); + } + // For an arithmetic operation, the implied arithmetic must be well-formed. if (Form == Arithmetic) { // GCC does not enforce these rules for GNU atomics, but we do to help catch @@ -8946,7 +8953,7 @@ ExprResult Sema::BuiltinAtomicOverloaded(ExprResult TheCallResult) { const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>(); if (!pointerType) { Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer) - << FirstArg->getType() << FirstArg->getSourceRange(); + << FirstArg->getType() << 0 << FirstArg->getSourceRange(); return ExprError(); } @@ -8954,7 +8961,7 @@ ExprResult Sema::BuiltinAtomicOverloaded(ExprResult TheCallResult) { if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && !ValType->isBlockPointerType()) { Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intptr) - << FirstArg->getType() << FirstArg->getSourceRange(); + << FirstArg->getType() << 0 << FirstArg->getSourceRange(); return ExprError(); } diff --git a/clang/test/Sema/atomic-ops.c b/clang/test/Sema/atomic-ops.c index 1d36667d6cf40..2024b81ce6aec 100644 --- a/clang/test/Sema/atomic-ops.c +++ b/clang/test/Sema/atomic-ops.c @@ -639,6 +639,38 @@ void memory_checks(_Atomic(int) *Ap, int *p, int val) { (void)__atomic_compare_exchange_n(p, p, val, 0, memory_order_seq_cst, -1); // expected-warning {{memory order argument to atomic operation is invalid}} } +struct Z { + char z[]; +}; + +void zeroSizeArgError(struct Z *a, struct Z *b, struct Z *c) { + __atomic_exchange(b, b, c, memory_order_relaxed); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_exchange(b, b, c, memory_order_acq_rel); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_exchange(b, b, c, memory_order_acquire); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_exchange(b, b, c, memory_order_consume); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_exchange(b, b, c, memory_order_release); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_exchange(b, b, c, memory_order_seq_cst); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_load(a, b, memory_order_relaxed); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_load(a, b, memory_order_acq_rel); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_load(a, b, memory_order_acquire); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_load(a, b, memory_order_consume); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_load(a, b, memory_order_release); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_load(a, b, memory_order_seq_cst); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_store(a, b, memory_order_relaxed); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_store(a, b, memory_order_acq_rel); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_store(a, b, memory_order_acquire); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_store(a, b, memory_order_consume); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_store(a, b, memory_order_release); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_store(a, b, memory_order_seq_cst); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_compare_exchange(a, b, c, 0, memory_order_relaxed, memory_order_relaxed); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_compare_exchange(a, b, c, 0, memory_order_acq_rel, memory_order_acq_rel); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_compare_exchange(a, b, c, 0, memory_order_acquire, memory_order_acquire); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_compare_exchange(a, b, c, 0, memory_order_consume, memory_order_consume); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_compare_exchange(a, b, c, 0, memory_order_release, memory_order_release); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + __atomic_compare_exchange(a, b, c, 0, memory_order_seq_cst, memory_order_seq_cst); // expected-error {{address argument to atomic builtin must be a pointer to a non-zero-sized object}} + +} + void nullPointerWarning(void) { volatile _Atomic(int) vai; _Atomic(int) ai; From 47803f41e40887bbbd371af6a1f2228e5a0acd6a Mon Sep 17 00:00:00 2001 From: hhuebner <hendrik.huebne...@gmail.com> Date: Sat, 25 May 2024 00:46:47 +0200 Subject: [PATCH 2/2] Add release notes entry --- clang/docs/ReleaseNotes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 54b58b1ae99fb..7cb821b64585d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -681,6 +681,7 @@ Bug Fixes to C++ Support whose type is `decltype(auto)`. Fixes (#GH68885). - Clang now correctly treats the noexcept-specifier of a friend function to be a complete-class context. - Fix an assertion failure when parsing an invalid members of an anonymous class. (#GH85447) +- Fix crash when atomic builtins are called with pointer to zero-size struct (#GH90330) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits