Closed fibrechannelscsi closed 1 year ago
cc @asl
So, the crash itself is here:
sil shared [transparent] [thunk] @$s2pb8MiniLoopV13TangentVectorVSa16_DifferentiationAF14DifferentiableRzlE0G4ViewVyAIySf_G_GSqA2fGRzlEADVySaySaySfGG_GIegnor_TJSpSSUpSrUSUP : $@convention(thin) (@in_guaranteed MiniLoop.TangentVector, @guaranteed @callee_guaranteed (@in_guaranteed MiniLoop.TangentVector) -> (@owned Array<Array<Float>.DifferentiableView>.DifferentiableView, @out Optional<Array<Array<Float>>>.TangentVector)) -> @out Optional<Array<Array<Float>>>.TangentVector {
// %0 // user: %3
// %1 // user: %3
// %2 // user: %3
bb0(%0 : $*Optional<Array<Array<Float>>>.TangentVector, %1 : $*MiniLoop.TangentVector, %2 : $@callee_guaranteed (@in_guaranteed MiniLoop.TangentVector) -> (@owned Array<Array<Float>.DifferentiableView>.DifferentiableView, @out Optional<Array<Array<Float>>>.TangentVector)):
%3 = apply %2(%0, %1) : $@callee_guaranteed (@in_guaranteed MiniLoop.TangentVector) -> (@owned Array<Array<Float>.DifferentiableView>.DifferentiableView, @out Optional<Array<Array<Float>>>.TangentVector) // user: %4
release_value %3 : $Array<Array<Float>.DifferentiableView>.DifferentiableView // id: %4
%5 = tuple () // user: %6
return %5 : $() // id: %6
} // end sil function '$s2pb8MiniLoopV13TangentVectorVSa16_DifferentiationAF14DifferentiableRzlE0G4ViewVyAIySf_G_GSqA2fGRzlEADVySaySaySfGG_GIegnor_TJSpSSUpSrUSUP'
The address of %2
that got applied is wrong in the second time. The thunk itself is partially applied in autodiff subset parameters thunk for reverse-mode derivative from MiniLoop.init(results:other:). And everything it recursively partially applied 2 or 3 times at this point :)
And everything reproduces if run
is reduced down to:
@differentiable(reverse)
public func run(params: MinParams) -> Output {
for t in 0 ... 1 {
}
let res = MiniLoop(other: params._twoDArray).results
return Output(results: res)
}
loop is essential here.
So, the address of %2
is 0x08d0eef4ea1dadab
. This is the particular pattern that is used feel the freed memory. So we're having some use already freed heap object.
Here is the relevant code in question:
%41 = builtin "autoDiffProjectTopLevelSubcontext"(%2 : $Builtin.NativeObject) : $Builtin.RawPointer // user: %42
%42 = pointer_to_address %41 : $Builtin.RawPointer to [strict] $*(predecessor: _AD__$s2pb3run6paramsAA6OutputVAA9MinParamsV_tF_bb3__Pred__src_0_wrt_0, @callee_guaranteed (@in_guaranteed MiniLoop.TangentVector) -> @out Optional<Array<Array<Float>>>.TangentVector, @callee_guaranteed (@guaranteed Output.TangentVector) -> @owned Array<Array<Float>.DifferentiableView>.DifferentiableView) // user: %43
%43 = load %42 : $*(predecessor: _AD__$s2pb3run6paramsAA6OutputVAA9MinParamsV_tF_bb3__Pred__src_0_wrt_0, @callee_guaranteed (@in_guaranteed MiniLoop.TangentVector) -> @out Optional<Array<Array<Float>>>.TangentVector, @callee_guaranteed (@guaranteed Output.TangentVector) -> @owned Array<Array<Float>.DifferentiableView>.DifferentiableView) // users: %46, %45, %44
%44 = tuple_extract %43 : $(predecessor: _AD__$s2pb3run6paramsAA6OutputVAA9MinParamsV_tF_bb3__Pred__src_0_wrt_0, @callee_guaranteed (@in_guaranteed MiniLoop.TangentVector) -> @out Optional<Array<Array<Float>>>.TangentVector, @callee_guaranteed (@guaranteed Output.TangentVector) -> @owned Array<Array<Float>.DifferentiableView>.DifferentiableView), 0 // user: %89
%45 = tuple_extract %43 : $(predecessor: _AD__$s2pb3run6paramsAA6OutputVAA9MinParamsV_tF_bb3__Pred__src_0_wrt_0, @callee_guaranteed (@in_guaranteed MiniLoop.TangentVector) -> @out Optional<Array<Array<Float>>>.TangentVector, @callee_guaranteed (@guaranteed Output.TangentVector) -> @owned Array<Array<Float>.DifferentiableView>.DifferentiableView), 1 // users: %70, %69
%46 = tuple_extract %43 : $(predecessor: _AD__$s2pb3run6paramsAA6OutputVAA9MinParamsV_tF_bb3__Pred__src_0_wrt_0, @callee_guaranteed (@in_guaranteed MiniLoop.TangentVector) -> @out Optional<Array<Array<Float>>>.TangentVector, @callee_guaranteed (@guaranteed Output.TangentVector) -> @owned Array<Array<Float>.DifferentiableView>.DifferentiableView), 2 // users: %48, %47
%47 = apply %46(%1) : $@callee_guaranteed (@guaranteed Output.TangentVector) -> @owned Array<Array<Float>.DifferentiableView>.DifferentiableView // users: %88, %53, %51, %50
strong_release %46 : $@callee_guaranteed (@guaranteed Output.TangentVector) -> @owned Array<Array<Float>.DifferentiableView>.DifferentiableView // id: %48
Essentially %48
releases %46
and it got freed, so we're having use-after-free for the second try
Thanks for taking a look!
Description The code shown below will crash at runtime with a SIGABRT / double free.
Steps to reproduce Paste the code below into a single file, compile, and run:
Expected behavior The program should print at least
TangentVector(_twoDArray: [])
, then exit with an exit code of 0.Environment
Additional context Running the pullback just once (i.e., removing the line immediately above
print(grad)
) will cause the program to exit without error. Further, omitting the line witharrayOfSIMDs.update
will also cause the program to exit without error. It's likely there is memory corruption occurring in and aroundupdate()
; I have seeniCount
be set to some large, nonsensical integer on occasion.