BUG: Make RangeIndex._data read-only to prevent external mutation - #67462
BUG: Make RangeIndex._data read-only to prevent external mutation#67462Benlite777 wants to merge 3 commits into
Conversation
085c38c to
4eedd4f
Compare
|
Apologies @Benlite777 - I didn't triage the original issue deep enough. #49663 already raises on main due to being read-only and should have been closed. Your issue is different. For yours, it's due to Instead, I believe we need to create a new @cache_readonly
def _references(self) -> BlockValuesRefs: # type: ignore[override]
result = BlockValuesRefs()
result.add_index_reference(self)
return resultcc @mroeschke for feedback on this proposal. |
rhshadrach
left a comment
There was a problem hiding this comment.
Will also need to rework the whatsnew slightly too.
| tm.assert_numpy_array_equal(result, expected) | ||
|
|
||
|
|
||
| def test_rangeindex_data_is_immutable(): |
There was a problem hiding this comment.
With my comment above, this test can be removed and I think you can just add RangeIndex to the parametrization of test_series_from_index
4eedd4f to
03c2991
Compare
|
@rhshadrach Thanks for the review! I've reworked the fix based on your feedback: Changes:
|
1992df1 to
be6961d
Compare
|
@rhshadrach Thanks for the detailed feedback! I've reworked the fix: Changes:
Waiting on @mroeschke's feedback on the approach as you mentioned. |
RangeIndex._simple_new set _references=None, bypassing Copy-on-Write reference tracking. This allowed a Series created from a RangeIndex to silently corrupt the index when modified, since no CoW copy was triggered. Add a @cache_readonly _references property on RangeIndex that lazily creates a BlockValuesRefs and registers the index reference. This avoids the upfront cost in _simple_new while ensuring CoW works correctly when the reference is actually needed.
89f98b6 to
b475696
Compare
What does this fix
When a
Seriesis created from aRangeIndex, the underlying cached_dataarray can be modified externally, silently corrupting the index. This happens because_datais decorated with@cache_readonlybut the returned numpy array is writeable.Fix
Mark the
_dataarray as read-only (data.flags.writeable = False) after construction, consistent with the same pattern used in:DatetimeIndex(pandas/core/indexes/datetimelike.py:1041)MultiIndex(pandas/core/indexes/multi.py:5133)Index.values(pandas/core/indexes/base.py:5256)Confirmed by @jbrockmendel that read-only is the desired approach.
Test
Added
test_rangeindex_data_is_immutablewhich verifies:_dataraisesValueErrorRetargeted from #67060 per @rhshadrach's comment.Fixes #67060