Skip to content

Commit 24d2049

Browse files
Merge pull request #31126 from ravikandhadai/oslog-diagnostic-improvement-sil
[OSLogOptimization] Fix a use-after-free bug in the function suppressGlobalStringTablePointerError of OSLogOptimization pass.
2 parents 6f44558 + a17b069 commit 24d2049

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed

lib/SIL/IR/SILConstants.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ llvm::cl::opt<unsigned>
2828
template <typename... T, typename... U>
2929
static InFlightDiagnostic diagnose(ASTContext &Context, SourceLoc loc,
3030
Diag<T...> diag, U &&... args) {
31+
// The lifetime of StringRef arguments will be extended as necessary by this
32+
// utility. The copy happens in onTentativeDiagnosticFlush at the bottom of
33+
// DiagnosticEngine.cpp, which is called when the destructor of the
34+
// InFlightDiagnostic returned by diagnose runs.
3135
return Context.Diags.diagnose(loc, diag, std::forward<U>(args)...);
3236
}
3337

@@ -939,8 +943,8 @@ void SymbolicValue::emitUnknownDiagnosticNotes(SILLocation fallbackLoc) {
939943
triggerLocSkipsInternalLocs);
940944
return;
941945
case UnknownReason::Trap: {
942-
const char *message = unknownReason.getTrapMessage();
943-
diagnose(ctx, diagLoc, diag::constexpr_trap, StringRef(message));
946+
diagnose(ctx, diagLoc, diag::constexpr_trap,
947+
unknownReason.getTrapMessage());
944948
if (emitTriggerLocInDiag)
945949
diagnose(ctx, triggerLoc, diag::constexpr_trap_operation,
946950
triggerLocSkipsInternalLocs);
@@ -987,7 +991,7 @@ void SymbolicValue::emitUnknownDiagnosticNotes(SILLocation fallbackLoc) {
987991
std::string demangledCalleeName =
988992
demangleSymbolNameForDiagnostics(callee->getName());
989993
diagnose(ctx, diagLoc, diag::constexpr_found_callee_with_no_body,
990-
StringRef(demangledCalleeName));
994+
demangledCalleeName);
991995
if (emitTriggerLocInDiag)
992996
diagnose(ctx, triggerLoc, diag::constexpr_callee_with_no_body,
993997
triggerLocSkipsInternalLocs);
@@ -1040,7 +1044,7 @@ void SymbolicValue::emitUnknownDiagnosticNotes(SILLocation fallbackLoc) {
10401044
witnessMethodName);
10411045

10421046
diagnose(ctx, diagLoc, diag::constexpr_unresolvable_witness_call,
1043-
StringRef(witnessMethodName));
1047+
witnessMethodName);
10441048
if (emitTriggerLocInDiag)
10451049
diagnose(ctx, triggerLoc, diag::constexpr_no_witness_table_entry,
10461050
triggerLocSkipsInternalLocs);

lib/SILOptimizer/Mandatory/OSLogOptimization.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ using namespace Lowering;
108108
template <typename... T, typename... U>
109109
static void diagnose(ASTContext &Context, SourceLoc loc, Diag<T...> diag,
110110
U &&... args) {
111+
// The lifetime of StringRef arguments will be extended as necessary by this
112+
// utility. The copy happens in onTentativeDiagnosticFlush at the bottom of
113+
// DiagnosticEngine.cpp, which is called when the destructor of the
114+
// InFlightDiagnostic returned by diagnose runs.
111115
Context.Diags.diagnose(loc, diag, std::forward<U>(args)...);
112116
}
113117

@@ -365,9 +369,8 @@ static bool diagnoseSpecialErrors(SILInstruction *unevaluableInst,
365369

366370
if (unknownReason.getKind() == UnknownReason::Trap) {
367371
// We have an assertion failure or fatal error.
368-
const char *message = unknownReason.getTrapMessage();
369372
diagnose(ctx, sourceLoc, diag::oslog_constant_eval_trap,
370-
StringRef(message));
373+
unknownReason.getTrapMessage());
371374
return true;
372375
}
373376
if (unknownReason.getKind() == UnknownReason::TooManyInstructions) {
@@ -1431,19 +1434,28 @@ suppressGlobalStringTablePointerError(SingleValueInstruction *oslogMessage) {
14311434
SmallVector<SILInstruction *, 8> users;
14321435
getTransitiveUsers(oslogMessage, users);
14331436

1437+
// Collect all globalStringTablePointer instructions.
1438+
SmallVector<BuiltinInst *, 4> globalStringTablePointerInsts;
14341439
for (SILInstruction *user : users) {
14351440
BuiltinInst *bi = dyn_cast<BuiltinInst>(user);
1436-
if (!bi ||
1437-
bi->getBuiltinInfo().ID != BuiltinValueKind::GlobalStringTablePointer)
1438-
continue;
1439-
// Replace this builtin by a string_literal instruction for an empty string.
1441+
if (bi &&
1442+
bi->getBuiltinInfo().ID == BuiltinValueKind::GlobalStringTablePointer)
1443+
globalStringTablePointerInsts.push_back(bi);
1444+
}
1445+
1446+
// Replace the globalStringTablePointer builtins by a string_literal
1447+
// instruction for an empty string and clean up dead code.
1448+
InstructionDeleter deleter;
1449+
for (BuiltinInst *bi : globalStringTablePointerInsts) {
14401450
SILBuilderWithScope builder(bi);
14411451
StringLiteralInst *stringLiteral = builder.createStringLiteral(
14421452
bi->getLoc(), StringRef(""), StringLiteralInst::Encoding::UTF8);
14431453
bi->replaceAllUsesWith(stringLiteral);
1444-
// Here, the bulitin instruction is dead, so clean it up.
1445-
eliminateDeadInstruction(bi);
1454+
// The bulitin instruction is likely dead. But since we are iterating over
1455+
// many instructions, do the cleanup at the end.
1456+
deleter.trackIfDead(bi);
14461457
}
1458+
deleter.cleanUpDeadInstructions();
14471459
}
14481460

14491461
/// If the SILInstruction is an initialization of OSLogMessage, return the

0 commit comments

Comments
 (0)