Skip to content

Commit e3750fb

Browse files
authored
[Clang] Add diagnostic about "%P" specifier with Objective-C pointers (#89977)
A Darwin extension '%P' combined with an Objective-C pointer seems to always be a bug. '%P' will dump bytes at the pointed-to address (in contrast to '%p' which dumps the pointer itself). This extension is only allowed in "OS Log" contexts and is intended to be used like `%{uuid_t}.*16P` or `%{timeval}.*P`. If an ObjC pointer is used, then the internal runtime structure (aka, the is-a pointer and other runtime metadata) will be dumped, which (IMO) is never the expectation. A simple diagnostic can help flag these scenarios. Resolves #89968 Co-authored-by: Jared Grubb <jgrubb@apple.com>
1 parent 2903df0 commit e3750fb

File tree

3 files changed

+18
-1
lines changed

3 files changed

+18
-1
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9901,6 +9901,9 @@ def warn_format_invalid_annotation : Warning<
99019901
def warn_format_P_no_precision : Warning<
99029902
"using '%%P' format specifier without precision">,
99039903
InGroup<Format>;
9904+
def warn_format_P_with_objc_pointer : Warning<
9905+
"using '%%P' format specifier with an Objective-C pointer results in dumping runtime object structure, not object value">,
9906+
InGroup<Format>;
99049907
def warn_printf_ignored_flag: Warning<
99059908
"flag '%0' is ignored when flag '%1' is present">,
99069909
InGroup<Format>;

clang/lib/Sema/SemaChecking.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12559,6 +12559,17 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
1255912559
return true;
1256012560
}
1256112561

12562+
// Diagnose attempts to use '%P' with ObjC object types, which will result in
12563+
// dumping raw class data (like is-a pointer), not actual data.
12564+
if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::PArg &&
12565+
ExprTy->isObjCObjectPointerType()) {
12566+
const CharSourceRange &CSR =
12567+
getSpecifierRange(StartSpecifier, SpecifierLen);
12568+
EmitFormatDiagnostic(S.PDiag(diag::warn_format_P_with_objc_pointer),
12569+
E->getExprLoc(), false, CSR);
12570+
return true;
12571+
}
12572+
1256212573
ArgType::MatchKind ImplicitMatch = ArgType::NoMatch;
1256312574
ArgType::MatchKind Match = AT.matchesType(S.Context, ExprTy);
1256412575
ArgType::MatchKind OrigMatch = Match;

clang/test/SemaObjC/format-strings-oslog.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,18 @@ void test_os_log_format(const char *pc, int i, void *p, void *buf) {
4444
}
4545

4646
// Test os_log_format primitive with ObjC string literal format argument.
47-
void test_objc(const char *pc, int i, void *p, void *buf, NSString *nss) {
47+
void test_objc(const char *pc, int i, void *p, void *buf, NSString *nss, id obj) {
4848
__builtin_os_log_format(buf, @"");
4949
__builtin_os_log_format(buf, @"%d"); // expected-warning {{more '%' conversions than data arguments}}
5050
__builtin_os_log_format(buf, @"%d", i);
51+
5152
__builtin_os_log_format(buf, @"%P", p); // expected-warning {{using '%P' format specifier without precision}}
5253
__builtin_os_log_format(buf, @"%.10P", p);
5354
__builtin_os_log_format(buf, @"%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
5455
__builtin_os_log_format(buf, @"%.*P", i, p);
5556
__builtin_os_log_format(buf, @"%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
57+
__builtin_os_log_format(buf, @"%.8P", nss); // expected-warning {{using '%P' format specifier with an Objective-C pointer results in dumping runtime object structure, not object value}}
58+
__builtin_os_log_format(buf, @"%.*P", i, obj); // expected-warning {{using '%P' format specifier with an Objective-C pointer results in dumping runtime object structure, not object value}}
5659

5760
__builtin_os_log_format(buf, @"%{private}s", pc);
5861
__builtin_os_log_format(buf, @"%@", nss);

0 commit comments

Comments
 (0)