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

Reply via email to