https://github.com/ChenMiaoi created
https://github.com/llvm/llvm-project/pull/229010
Clang implicitly adds `format_arg(1)` to `__CFStringMakeConstantString`,
including declarations created during error recovery. A zero-argument call can
therefore make `checkFormatStringExpr` access a nonexistent argument.
Reproducer:
```c
void a(char *) __attribute__((format(__CFString__, 1, 2)));
void b() { a(__CFStringMakeConstantString()); }
```
Before this change, an assertions-enabled build crashes after reporting the
source errors (diagnostic excerpts):
```text
error: call to undeclared function '__CFStringMakeConstantString';
ISO C99 and later do not support implicit function declarations
error: incompatible integer to pointer conversion passing 'int' to parameter of
type 'char *'
Assertion `Arg < getNumArgs() && "Arg access out of range!"' failed.
```
Check the `format_arg` index against `CE->getNumArgs()` before calling
`CE->getArg()`. Return `SLCT_NotALiteral` when the argument is missing so
normal diagnostics can continue.
After this change, the compiler reports diagnostics and exits with status 1
without crashing (diagnostic excerpts):
```text
error: call to undeclared function '__CFStringMakeConstantString';
ISO C99 and later do not support implicit function declarations
error: incompatible integer to pointer conversion passing 'int' to parameter of
type 'char *'
warning: format string is not a string literal (potentially insecure)
```
Fixes #225034
>From 7a0b2f93ae262b941600ce2e813ca5621a9020d3 Mon Sep 17 00:00:00 2001
From: Chen Miao <[email protected]>
Date: Mon, 5 Oct 2026 16:41:51 +0800
Subject: [PATCH] [clang][Sema] Avoid out-of-bounds format_arg access
Clang implicitly adds `format_arg(1)` to `__CFStringMakeConstantString`,
including declarations created during error recovery. A zero-argument
call can therefore make `checkFormatStringExpr` access a nonexistent
argument.
Reproducer:
```c
void a(char *) __attribute__((format(__CFString__, 1, 2)));
void b() { a(__CFStringMakeConstantString()); }
```
Before this change, an assertions-enabled build crashes after reporting
the source errors (diagnostic excerpts):
```text
error: call to undeclared function '__CFStringMakeConstantString';
ISO C99 and later do not support implicit function declarations
error: incompatible integer to pointer conversion passing 'int' to parameter of
type 'char *'
Assertion `Arg < getNumArgs() && "Arg access out of range!"' failed.
```
Check the `format_arg` index against `CE->getNumArgs()` before calling
`CE->getArg()`. Return `SLCT_NotALiteral` when the argument is missing so
normal diagnostics can continue.
After this change, the compiler reports diagnostics and exits with
status 1 without crashing (diagnostic excerpts):
```text
error: call to undeclared function '__CFStringMakeConstantString';
ISO C99 and later do not support implicit function declarations
error: incompatible integer to pointer conversion passing 'int' to parameter of
type 'char *'
warning: format string is not a string literal (potentially insecure)
```
Fixes #225034
---
clang/lib/Sema/SemaChecking.cpp | 7 ++++++-
clang/test/Sema/format-strings-cfstring.c | 18 ++++++++++++++++++
2 files changed, 24 insertions(+), 1 deletion(-)
create mode 100644 clang/test/Sema/format-strings-cfstring.c
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 0531dfa877fbd..eb5982f10e763 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -7710,7 +7710,12 @@ checkFormatStringExpr(Sema &S, const StringLiteral
*ReferenceFormatString,
bool IsFirst = true;
StringLiteralCheckType CommonResult;
for (const auto *FA : ND->specific_attrs<FormatArgAttr>()) {
- const Expr *Arg = CE->getArg(FA->getFormatIdx().getASTIndex());
+ // An implicitly added attribute may refer to a missing argument.
+ // https://github.com/llvm/llvm-project/issues/225034
+ unsigned ArgIndex = FA->getFormatIdx().getASTIndex();
+ if (ArgIndex >= CE->getNumArgs())
+ return SLCT_NotALiteral;
+ const Expr *Arg = CE->getArg(ArgIndex);
StringLiteralCheckType Result = checkFormatStringExpr(
S, ReferenceFormatString, Arg, Args, APK, format_idx, firstDataArg,
Type, CallType, InFunctionCall, CheckedVarArgs, UncoveredArg,
diff --git a/clang/test/Sema/format-strings-cfstring.c
b/clang/test/Sema/format-strings-cfstring.c
new file mode 100644
index 0000000000000..776a82e7c3eb7
--- /dev/null
+++ b/clang/test/Sema/format-strings-cfstring.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c11 -fsyntax-only -Wno-gcc-compat
-verify=expected,implicit %s
+// RUN: %clang_cc1 -std=c11 -fsyntax-only -Wno-gcc-compat -DDECLARE_CFSTRING
-verify %s
+
+// An implicitly added format_arg attribute may refer to a missing argument,
+// both during error recovery and with a non-prototype declaration.
+// https://github.com/llvm/llvm-project/issues/225034
+#ifdef DECLARE_CFSTRING
+char *__CFStringMakeConstantString();
+#endif
+
+void a(char *) __attribute__((format(__CFString__, 1, 2))); // implicit-note
{{passing argument to parameter here}}
+
+void b(void) {
+ a(__CFStringMakeConstantString()); // expected-warning {{format string is
not a string literal (potentially insecure)}}
+ // expected-note@-1 {{treat the string as an argument to avoid this}}
+ // implicit-error@-2 {{call to undeclared function
'__CFStringMakeConstantString'}}
+ // implicit-error@-3 {{incompatible integer to pointer conversion passing
'int' to parameter of type 'char *'}}
+}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits