Skip to content

Commit

Permalink
Make ByteArrayWrapper safe for use as key in Map
Browse files Browse the repository at this point in the history
The underlying byte[] is mutable and could accidentally be changed after
instantiation of the wrapper object. To ensure that the hashCode or the
(natural or fast) order of the object does not change, the data must be
copied defensively.
  • Loading branch information
bertm committed Nov 17, 2024
1 parent f1a9c2e commit f3edebf
Showing 1 changed file with 18 additions and 24 deletions.
42 changes: 18 additions & 24 deletions src/freenet/support/ByteArrayWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,24 @@
*/
public class ByteArrayWrapper implements Comparable<ByteArrayWrapper> {

private final byte[] buf;
private int hashCode;
private final byte[] data;
private final int hashCode;

public static final Comparator<ByteArrayWrapper> FAST_COMPARATOR = new Comparator<ByteArrayWrapper>() {

@Override
public int compare(ByteArrayWrapper o1, ByteArrayWrapper o2) {
if(o1.hashCode > o2.hashCode) return 1;
if(o1.hashCode < o2.hashCode) return -1;
return o1.compareTo(o2);
}

};
public static final Comparator<ByteArrayWrapper> FAST_COMPARATOR = Comparator
.comparingInt(ByteArrayWrapper::hashCode)
.thenComparing(Comparator.naturalOrder());

public ByteArrayWrapper(byte[] data) {
buf = data;
hashCode = Fields.hashCode(buf);
this.data = Arrays.copyOf(data, data.length);
this.hashCode = Arrays.hashCode(this.data);
}

@Override
public boolean equals(Object o) {
if(o instanceof ByteArrayWrapper) {
ByteArrayWrapper b = (ByteArrayWrapper) o;
if(b.buf == buf) return true;
return Arrays.equals(b.buf, buf);
public boolean equals(Object other) {
if (this == other) return true;
if (other instanceof ByteArrayWrapper) {
ByteArrayWrapper b = (ByteArrayWrapper) other;
return this.hashCode == b.hashCode && Arrays.equals(this.data, b.data);
}
return false;
}
Expand All @@ -46,14 +39,15 @@ public int hashCode() {
return hashCode;
}

/** DO NOT MODIFY THE RETURNED DATA! */
public byte[] get() {
return buf;
return Arrays.copyOf(data, data.length);
}

@Override
public int compareTo(ByteArrayWrapper arg) {
if(this == arg) return 0;
return Fields.compareBytes(buf, arg.buf);
public int compareTo(ByteArrayWrapper other) {
if (this == other) {
return 0;
}
return Fields.compareBytes(this.data, other.data);
}
}

0 comments on commit f3edebf

Please sign in to comment.