Skip to content

Commit b347e05

Browse files
authored
Merge pull request #23939 from gottesmm/swift-5.1-branch-rdar49794321
[5.1][ownership] Fix a corner case in the linear lifetime checker.
2 parents bf76471 + 71482a2 commit b347e05

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

lib/SIL/LinearLifetimeChecker.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,25 @@ LinearLifetimeError swift::valueHasLinearLifetime(
486486
// have been detected by initializing our consuming uses. So we are done.
487487
if (consumingUses.size() == 1 &&
488488
consumingUses[0].getParent() == value->getParentBlock()) {
489+
// Check if any of our non consuming uses are not in the parent block. We
490+
// flag those as additional use after frees. Any in the same block, we would
491+
// have flagged.
492+
if (llvm::any_of(nonConsumingUses, [&](BranchPropagatedUser user) {
493+
return user.getParent() != value->getParentBlock();
494+
})) {
495+
state.error.handleUseAfterFree([&] {
496+
llvm::errs() << "Function: '" << value->getFunction()->getName()
497+
<< "'\n"
498+
<< "Found use after free due to unvisited non lifetime "
499+
"ending uses?!\n"
500+
<< "Value: " << *value << " Remaining Users:\n";
501+
for (const auto &user : nonConsumingUses) {
502+
llvm::errs() << "User: " << *user.getInst();
503+
}
504+
llvm::errs() << "\n";
505+
});
506+
}
507+
489508
return state.error;
490509
}
491510

test/SIL/ownership-verifier/over_consume.sil

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ case some(T)
2222
case none
2323
}
2424

25+
protocol Error {}
26+
27+
struct NativeObjectPair {
28+
var obj1 : Builtin.NativeObject
29+
var obj2 : Builtin.NativeObject
30+
}
31+
2532
class SuperKlass {
2633
func doSomething()
2734
}
@@ -485,3 +492,35 @@ bb0(%0 : @guaranteed $ClassProtConformingRef, %1 : @owned $ClassProtConformingRe
485492
%5 = tuple(%3 : $ClassProt, %4 : $ClassProt)
486493
return %5 : $(ClassProt, ClassProt)
487494
}
495+
496+
sil [ossa] @eliminate_copy_try_apple_callee : $@convention(thin) (@owned Builtin.NativeObject) -> @error Error {
497+
entry(%0 : @owned $Builtin.NativeObject):
498+
%9999 = tuple()
499+
return %9999 : $()
500+
}
501+
502+
503+
// CHECK-LABEL: Function: 'use_after_free_consume_in_same_block'
504+
// CHECK: Found use after free due to unvisited non lifetime ending uses?!
505+
// CHECK: Value: %3 = copy_value %2 : $Builtin.NativeObject
506+
// CHECK: Remaining Users:
507+
// CHECK: User: %10 = apply %7(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
508+
sil [ossa] @use_after_free_consume_in_same_block : $@convention(thin) (@owned NativeObjectPair) -> @error Error {
509+
bb0(%0 : @owned $NativeObjectPair):
510+
%1 = begin_borrow %0 : $NativeObjectPair
511+
%2 = struct_extract %1 : $NativeObjectPair, #NativeObjectPair.obj1
512+
%3 = copy_value %2 : $Builtin.NativeObject
513+
end_borrow %1 : $NativeObjectPair
514+
destroy_value %0 : $NativeObjectPair
515+
%4 = function_ref @eliminate_copy_try_apple_callee : $@convention(thin) (@owned Builtin.NativeObject) -> @error Error
516+
%5 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
517+
try_apply %4(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> @error Error, normal bb1, error bb2
518+
519+
bb1(%errorEmptyTup: $()):
520+
apply %5(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
521+
%9999 = tuple()
522+
return %9999 : $()
523+
524+
bb2(%error : @owned $Error):
525+
throw %error : $Error
526+
}

0 commit comments

Comments
 (0)