Skip to content

Commit 41b83b4

Browse files
authored
No longer assert on incorrect attribute argument index (#133766)
Fixes an assertion when referencing an out-of-bounds parameter via a function attribute whose argument list refers to parameters by index and the function is variadic. e.g., __attribute__ ((__format_arg__(2))) void test (int i, ...) { } Fixes #61635
1 parent 290d7b8 commit 41b83b4

File tree

4 files changed

+32
-10
lines changed

4 files changed

+32
-10
lines changed

clang/docs/ReleaseNotes.rst

+9
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,15 @@ Improvements to Clang's diagnostics
298298

299299
- Improve the ``-Wundefined-func-template`` warning when a function template is not instantiated due to being unreachable in modules.
300300

301+
- Fixed an assertion when referencing an out-of-bounds parameter via a function
302+
attribute whose argument list refers to parameters by index and the function
303+
is variadic. e.g.,
304+
.. code-block:: c
305+
306+
__attribute__ ((__format_arg__(2))) void test (int i, ...) { }
307+
308+
Fixes #GH61635
309+
301310
Improvements to Clang's time-trace
302311
----------------------------------
303312

clang/include/clang/Sema/Sema.h

+6-5
Original file line numberDiff line numberDiff line change
@@ -4796,10 +4796,10 @@ class Sema final : public SemaBase {
47964796
///
47974797
/// \returns true if IdxExpr is a valid index.
47984798
template <typename AttrInfo>
4799-
bool checkFunctionOrMethodParameterIndex(const Decl *D, const AttrInfo &AI,
4800-
unsigned AttrArgNum,
4801-
const Expr *IdxExpr, ParamIdx &Idx,
4802-
bool CanIndexImplicitThis = false) {
4799+
bool checkFunctionOrMethodParameterIndex(
4800+
const Decl *D, const AttrInfo &AI, unsigned AttrArgNum,
4801+
const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis = false,
4802+
bool CanIndexVariadicArguments = false) {
48034803
assert(isFunctionOrMethodOrBlockForAttrSubject(D));
48044804

48054805
// In C++ the implicit 'this' function parameter also counts.
@@ -4820,7 +4820,8 @@ class Sema final : public SemaBase {
48204820
}
48214821

48224822
unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX);
4823-
if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
4823+
if (IdxSource < 1 ||
4824+
((!IV || !CanIndexVariadicArguments) && IdxSource > NumParams)) {
48244825
Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
48254826
<< &AI << AttrArgNum << IdxExpr->getSourceRange();
48264827
return false;

clang/lib/Sema/SemaDeclAttr.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -1315,7 +1315,10 @@ static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
13151315
for (unsigned I = 0; I < AL.getNumArgs(); ++I) {
13161316
Expr *Ex = AL.getArgAsExpr(I);
13171317
ParamIdx Idx;
1318-
if (!S.checkFunctionOrMethodParameterIndex(D, AL, I + 1, Ex, Idx))
1318+
if (!S.checkFunctionOrMethodParameterIndex(
1319+
D, AL, I + 1, Ex, Idx,
1320+
/*CanIndexImplicitThis=*/false,
1321+
/*CanIndexVariadicArguments=*/true))
13191322
return;
13201323

13211324
// Is the function argument a pointer type?
@@ -5756,13 +5759,17 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
57565759
}
57575760

57585761
ParamIdx ArgumentIdx;
5759-
if (!S.checkFunctionOrMethodParameterIndex(D, AL, 2, AL.getArgAsExpr(1),
5760-
ArgumentIdx))
5762+
if (!S.checkFunctionOrMethodParameterIndex(
5763+
D, AL, 2, AL.getArgAsExpr(1), ArgumentIdx,
5764+
/*CanIndexImplicitThis=*/false,
5765+
/*CanIndexVariadicArguments=*/true))
57615766
return;
57625767

57635768
ParamIdx TypeTagIdx;
5764-
if (!S.checkFunctionOrMethodParameterIndex(D, AL, 3, AL.getArgAsExpr(2),
5765-
TypeTagIdx))
5769+
if (!S.checkFunctionOrMethodParameterIndex(
5770+
D, AL, 3, AL.getArgAsExpr(2), TypeTagIdx,
5771+
/*CanIndexImplicitThis=*/false,
5772+
/*CanIndexVariadicArguments=*/true))
57665773
return;
57675774

57685775
bool IsPointer = AL.getAttrName()->getName() == "pointer_with_type_tag";

clang/test/Sema/attr-args.c

+5
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,8 @@ inline __attribute__((stdcall(a))) void *f8(void); // expected-error {{'stdcall
2424
inline __attribute__((used(a))) void *f9(void); // expected-error {{'used' attribute takes no arguments}}
2525
inline __attribute__((unused(a))) void *f10(void); // expected-error {{'unused' attribute takes no arguments}}
2626
inline __attribute__((weak(a))) void *f11(void); // expected-error {{'weak' attribute takes no arguments}}
27+
28+
__attribute__ ((__format_arg__(2))) // expected-error {{'__format_arg__' attribute parameter 1 is out of bounds}}
29+
void test (int, ...);
30+
31+
void __attribute__ ((alloc_size (2, 3))) *test2(int, ...); // expected-error {{'alloc_size' attribute parameter 1 is out of bounds}}

0 commit comments

Comments
 (0)