.llms/rules/ACR_raw_bitmap_from_closeable_ref.md
Severity: CRITICAL — #1 Fresco crash pattern: recycled bitmap use-after-free
For the full CloseableReference ownership and lifecycle rules, see https://fburl.com/closeable-references.
closeableRef.get() result stored in a class field (not a local variable)closeableImage.getUnderlyingBitmap() result passed to another componentBaseBitmapDataSubscriber.onNewResultImpl(bitmap) — bitmap escaping method scopeBitmap held without a corresponding CloseableReference keeping it aliveval/var bitmap: Bitmap = closeableRef.get() as a class fieldbitmap from a DataSubscriber callback to another thread or componentgetUnderlyingBitmap() result without calling bitmap.copy() firstCloseableReference.clone() (proper ownership transfer)bitmap.copy(config, true) before storing// BAD — Raw bitmap stored as field; Fresco may recycle it at any time
class ImageHolder {
var bitmap: Bitmap? = null // ❌ Dangling reference after CloseableRef closes
fun onImageReady(ref: CloseableReference<CloseableImage>) {
bitmap = (ref.get() as CloseableBitmap).underlyingBitmap
}
}
// GOOD — Hold the CloseableReference itself
class ImageHolder {
var imageRef: CloseableReference<CloseableImage>? = null // ✅ Keeps bitmap alive
fun onImageReady(ref: CloseableReference<CloseableImage>) {
CloseableReference.closeSafely(imageRef) // Close previous
imageRef = ref.clone() // Own a copy
}
fun release() {
CloseableReference.closeSafely(imageRef)
imageRef = null
}
}
// BAD — Bitmap from DataSubscriber escaping callback scope
override fun onNewResultImpl(bitmap: Bitmap?) {
subscriber.onBitmapLoaded(bitmap) // ❌ Bitmap only valid during this call!
}
// GOOD — Copy before passing out
override fun onNewResultImpl(bitmap: Bitmap?) {
val copy = bitmap?.copy(bitmap.config, true) // ✅ Independent copy
subscriber.onBitmapLoaded(copy)
}
FrescoDataSourceSubscriber passed Fresco-managed bitmap to UI thread without copy — recycled bitmap crashBaseBitmapDataSubscriber bitmap escaped to IconCompat.createWithAdaptiveBitmap() — "Can't copy a recycled bitmap"recycle() on Fresco-owned bitmap