Skip to content

Commit 2100dca

Browse files
committed
[os_log] Fix a CodeGen crash that occurs when arguments of struct,
class, or complex types are passed to _builtin_os_log_format This change fixes a crash in clang's CodeGen by ensuring that those arguments are ignored. rdar://139824423
1 parent 9e8761f commit 2100dca

File tree

2 files changed

+55
-16
lines changed

2 files changed

+55
-16
lines changed

clang/lib/AST/OSLog.cpp

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,22 +70,31 @@ class OSLogFormatStringHandler
7070
bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
7171
const char *StartSpecifier, unsigned SpecifierLen,
7272
const TargetInfo &) override {
73+
// Set the argument expression. Arguments of struct/class/complex types are
74+
// ignored.
75+
auto CheckAndSetArgExpr = [&](unsigned Idx, auto &ArgE) {
76+
const Expr *E = Args[Idx];
77+
if (E && (E->getType()->isRecordType() || E->getType()->isComplexType()))
78+
return false;
79+
ArgE = E;
80+
return true;
81+
};
82+
7383
if (!FS.consumesDataArgument() &&
7484
FS.getConversionSpecifier().getKind() !=
7585
clang::analyze_format_string::ConversionSpecifier::PrintErrno)
7686
return true;
7787

78-
ArgsData.emplace_back();
88+
ArgData ArgD;
7989
unsigned ArgIndex = FS.getArgIndex();
8090
if (ArgIndex < Args.size())
81-
ArgsData.back().E = Args[ArgIndex];
91+
if (!CheckAndSetArgExpr(ArgIndex, ArgD.E))
92+
return true;
8293

8394
// First get the Kind
84-
ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind());
85-
if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind &&
86-
!ArgsData.back().E) {
95+
ArgD.Kind = getKind(FS.getConversionSpecifier().getKind());
96+
if (ArgD.Kind != OSLogBufferItem::ErrnoKind && !ArgD.E) {
8797
// missing argument
88-
ArgsData.pop_back();
8998
return false;
9099
}
91100

@@ -97,10 +106,11 @@ class OSLogFormatStringHandler
97106
case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%s"
98107
break;
99108
case clang::analyze_format_string::OptionalAmount::Constant: // "%.16s"
100-
ArgsData.back().Size = precision.getConstantAmount();
109+
ArgD.Size = precision.getConstantAmount();
101110
break;
102111
case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s"
103-
ArgsData.back().Count = Args[precision.getArgIndex()];
112+
if (!CheckAndSetArgExpr(precision.getArgIndex(), ArgD.Count))
113+
return true;
104114
break;
105115
case clang::analyze_format_string::OptionalAmount::Invalid:
106116
return false;
@@ -113,10 +123,11 @@ class OSLogFormatStringHandler
113123
case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%P"
114124
return false; // length must be supplied with pointer format specifier
115125
case clang::analyze_format_string::OptionalAmount::Constant: // "%.16P"
116-
ArgsData.back().Size = precision.getConstantAmount();
126+
ArgD.Size = precision.getConstantAmount();
117127
break;
118128
case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P"
119-
ArgsData.back().Count = Args[precision.getArgIndex()];
129+
if (!CheckAndSetArgExpr(precision.getArgIndex(), ArgD.Count))
130+
return true;
120131
break;
121132
case clang::analyze_format_string::OptionalAmount::Invalid:
122133
return false;
@@ -125,22 +136,27 @@ class OSLogFormatStringHandler
125136
}
126137
default:
127138
if (FS.getPrecision().hasDataArgument()) {
128-
ArgsData.back().Precision = Args[FS.getPrecision().getArgIndex()];
139+
if (!CheckAndSetArgExpr(FS.getPrecision().getArgIndex(),
140+
ArgD.Precision))
141+
return true;
129142
}
130143
break;
131144
}
132145
if (FS.getFieldWidth().hasDataArgument()) {
133-
ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()];
146+
if (!CheckAndSetArgExpr(FS.getFieldWidth().getArgIndex(),
147+
ArgD.FieldWidth))
148+
return true;
134149
}
135150

136151
if (FS.isSensitive())
137-
ArgsData.back().Flags |= OSLogBufferItem::IsSensitive;
152+
ArgD.Flags |= OSLogBufferItem::IsSensitive;
138153
else if (FS.isPrivate())
139-
ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;
154+
ArgD.Flags |= OSLogBufferItem::IsPrivate;
140155
else if (FS.isPublic())
141-
ArgsData.back().Flags |= OSLogBufferItem::IsPublic;
156+
ArgD.Flags |= OSLogBufferItem::IsPublic;
142157

143-
ArgsData.back().MaskType = FS.getMaskType();
158+
ArgD.MaskType = FS.getMaskType();
159+
ArgsData.push_back(ArgD);
144160
return true;
145161
}
146162

clang/test/CodeGenObjC/os_log.m

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ + (id)m1;
1313

1414
C *c;
1515

16+
struct S {
17+
int a[4];
18+
};
19+
20+
struct S s;
21+
_Complex float cf;
22+
1623
@class NSString;
1724
extern __attribute__((visibility("default"))) NSString *GenString(void);
1825
void os_log_pack_send(void *);
@@ -123,3 +130,19 @@ void test_builtin_os_log5(void *buf) {
123130
__builtin_os_log_format(buf, "capabilities: %@", (0, GenString()));
124131
os_log_pack_send(buf);
125132
}
133+
134+
// CHECK-LABEL: define void @test_builtin_os_log6(
135+
// CHECK: call void @__os_log_helper_1_0_0(
136+
137+
void test_builtin_os_log6(void *buf) {
138+
__builtin_os_log_format(buf, "%.*s %.*P %*.*f", s, s, s, s, s, s, s);
139+
}
140+
141+
// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_0_0(
142+
143+
// CHECK-LABEL: define void @test_builtin_os_log7(
144+
// CHECK: call void @__os_log_helper_1_0_0(
145+
146+
void test_builtin_os_log7(void *buf) {
147+
__builtin_os_log_format(buf, "%.*s %.*P %*.*f", cf, cf, cf, cf, cf, cf, cf);
148+
}

0 commit comments

Comments
 (0)