mojira.dev
MC-178997

Storing a tag with a mismatched type in a numeric array tag succeeds even though its elements are not changed

The bug

Storing a tag with a mismatched type in a numeric array tag (byte/int/long array tag) does not throw an exception even though its elements result in the same as before.

How to reproduce

  1. /data modify storage mc-178997: array set value [B; 0B]
    /data modify storage mc-178997: array set value [B; 0B]
  2. /data modify storage mc-178997: array[0] set value 0b
    /data modify storage mc-178997: array[0] set value 0b

    → ✔ Nothing changed. The specified properties already have these values

  3. /data modify storage mc-178997: array[0] set value 0s
    /data modify storage mc-178997: array[0] set value 0s

    → ❌ Modified storage mc-178997:, this should not succeed because

  4. /data get storage mc-178997: array
    /data get storage mc-178997: array

    Storage mc-178997: has the following contents: [B; 0B], the contents are the same as in step 1.

Code analysis

The cause is that the tag to be set (newTag) is compared to the current tag (oldTag) before setTag that performs an implicit conversion. Two tags with different types never be equal, but can be equal after implicit conversion. In this case, setTag should not return 1 (successfully set).

// net.minecraft.commands.arguments.NbtPathArgument.IndexedElementNode

public int setTag(Tag tag, Supplier<Tag> supplier) {
    if (tag instanceof CollectionTag) {
        CollectionTag<?> collectionTag = (CollectionTag) tag;
        int size = collectionTag.size();
        int index = this.index < 0 ? size + this.index : this.index;
        if (0 <= index && index < size) {
            Tag oldTag = (Tag) collectionTag.get(index);
            Tag newTag = (Tag) supplier.get();
            if (!newTag.equals(oldTag) && collectionTag.setTag(index, newTag)) {
            //  ^^^^^^^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            //  comparison                implicit conversion and set

                return 1;
            }
        }
    }
    
    return 0;
}
// net.minecraft.commands.arguments.NbtPathArgument.IndexedElementNode

public int setTag(Tag tag, Supplier<Tag> supplier) {
    if (tag instanceof CollectionTag) {
        CollectionTag<?> collectionTag = (CollectionTag) tag;
        int size = collectionTag.size();
        int index = this.index < 0 ? size + this.index : this.index;
        if (0 <= index && index < size) {
            Tag oldTag = (Tag) collectionTag.get(index);
            Tag newTag = (Tag) supplier.get();
            if (!newTag.equals(oldTag) && collectionTag.setTag(index, newTag)) {
            //  ^^^^^^^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            //  comparison                implicit conversion and set

                return 1;
            }
        }
    }
    
    return 0;
}

Comments 0

No comments.

intsuc

(Unassigned)

Confirmed

Commands

nbt

1.15.2, 20w16a, 20w17a, 20w18a, 20w20b, ..., 24w33a, 1.21.4, 25w04a, 1.21.5, 25w16a

Retrieved