-
Bug
-
Resolution: Invalid
-
None
-
1.18.2, 22w19a
-
None
-
Community Consensus
-
(Unassigned)
The PaletteContainer#copy() method does not properly deep-copy, although it looks like it should. This currently does not have an impact on the game because all copies are only used for reading, but if that were to change, worlds could easily get corrupted.
When using this method, the internal storage is properly deep-copied. However, the palette copy (created by using Palette#copy()) keeps a reference to the original PaletteContainer's ResizeHandler. When triggering a resize by writing on a copy provided by PaletteContainer#copy(), the original container will be resized instead of the correct one. This can result in data corruption.
The problematic code can be seen below:
(#copy() calls Palette#copy() when creating a new Data object without providing a resizeHandler)
public PalettedContainer<T> copy() { return new PalettedContainer<>(this.registry, this.strategy, new PalettedContainer.Data<>(this.data.configuration(), this.data.storage().copy(), this.data.palette().copy())); }
(all palette types share the resizeHandler when copying because they have no other one to provide)
# LinearPalette @Override public Palette<T> copy() { return new LinearPalette<>(this.registry, (T[])((Object[])this.values.clone()), this.resizeHandler, this.bits, this.size); }
# HashMapPalette @Override public Palette<T> copy() { return new HashMapPalette<>(this.registry, this.bits, this.resizeHandler, this.values.copy()); }
# SingleValuePalette @Override public Palette<T> copy() { if (this.value == null) { throw new IllegalStateException("Use of an uninitialized palette"); } else { return this; } }