@@ -424,6 +424,8 @@ pub struct PyCData {
424424 pub buffer : PyRwLock < Cow < ' static , [ u8 ] > > ,
425425 /// pointer to base object or None (b_base)
426426 pub base : PyRwLock < Option < PyObjectRef > > ,
427+ /// Original from_buffer view, independent of the Python-mutable _objects dict.
428+ buffer_source : Option < PyObjectRef > ,
427429 /// byte offset within base's buffer (for field access)
428430 pub base_offset : AtomicCell < usize > ,
429431 /// index into base's b_objects list (b_index)
@@ -445,6 +447,7 @@ impl PyCData {
445447 Self {
446448 buffer : PyRwLock :: new ( Cow :: Owned ( vec ! [ 0u8 ; stg_info. size] ) ) ,
447449 base : PyRwLock :: new ( None ) ,
450+ buffer_source : None ,
448451 base_offset : AtomicCell :: new ( 0 ) ,
449452 index : AtomicCell :: new ( 0 ) ,
450453 objects : PyRwLock :: new ( None ) ,
@@ -458,6 +461,7 @@ impl PyCData {
458461 Self {
459462 buffer : PyRwLock :: new ( Cow :: Owned ( data) ) ,
460463 base : PyRwLock :: new ( None ) ,
464+ buffer_source : None ,
461465 base_offset : AtomicCell :: new ( 0 ) ,
462466 index : AtomicCell :: new ( 0 ) ,
463467 objects : PyRwLock :: new ( objects) ,
@@ -475,6 +479,7 @@ impl PyCData {
475479 Self {
476480 buffer : PyRwLock :: new ( Cow :: Owned ( data) ) ,
477481 base : PyRwLock :: new ( None ) ,
482+ buffer_source : None ,
478483 base_offset : AtomicCell :: new ( 0 ) ,
479484 index : AtomicCell :: new ( 0 ) ,
480485 objects : PyRwLock :: new ( objects) ,
@@ -496,6 +501,7 @@ impl PyCData {
496501 Self {
497502 buffer : PyRwLock :: new ( Cow :: Borrowed ( slice) ) ,
498503 base : PyRwLock :: new ( None ) ,
504+ buffer_source : None ,
499505 base_offset : AtomicCell :: new ( 0 ) ,
500506 index : AtomicCell :: new ( 0 ) ,
501507 objects : PyRwLock :: new ( None ) ,
@@ -525,6 +531,7 @@ impl PyCData {
525531 Self {
526532 buffer : PyRwLock :: new ( Cow :: Borrowed ( slice) ) ,
527533 base : PyRwLock :: new ( Some ( base_obj) ) ,
534+ buffer_source : None ,
528535 base_offset : AtomicCell :: new ( 0 ) ,
529536 index : AtomicCell :: new ( idx) ,
530537 objects : PyRwLock :: new ( None ) ,
@@ -554,12 +561,13 @@ impl PyCData {
554561 // Python stores the reference in a dict with key "-1" (unique_key pattern)
555562 let objects_dict = vm. ctx . new_dict ( ) ;
556563 objects_dict
557- . set_item ( "-1" , source, vm)
564+ . set_item ( "-1" , source. clone ( ) , vm)
558565 . expect ( "Failed to store buffer reference" ) ;
559566
560567 Self {
561568 buffer : PyRwLock :: new ( Cow :: Borrowed ( slice) ) ,
562569 base : PyRwLock :: new ( None ) ,
570+ buffer_source : Some ( source) ,
563571 base_offset : AtomicCell :: new ( 0 ) ,
564572 index : AtomicCell :: new ( 0 ) ,
565573 objects : PyRwLock :: new ( Some ( objects_dict. into ( ) ) ) ,
@@ -568,6 +576,13 @@ impl PyCData {
568576 }
569577 }
570578
579+ /// Storage owner used to detect aliased buffers without consulting _objects.
580+ pub ( crate ) fn buffer_base ( & self ) -> Option < PyObjectRef > {
581+ self . buffer_source
582+ . clone ( )
583+ . or_else ( || self . base . read ( ) . clone ( ) )
584+ }
585+
571586 /// Common implementation for from_buffer class method.
572587 /// Validates buffer, creates memoryview, and returns PyCData sharing memory with source.
573588 ///
0 commit comments