Skip to content

IpInetAddressMatcher throws ArrayIndexOutOfBoundsException instead of returning false for mismatched IPv4/IPv6 families #19733

Description

@minwoo-3

Describe the bug

IpInetAddressMatcher.matches(InetAddress) (introduced in 7.1, backing IpAddressMatcher/InetAddressMatchers) can throw ArrayIndexOutOfBoundsException instead of returning false when the address being checked and the configured address are of different IP families (IPv4 vs. IPv6).

The class-level Javadoc on IpAddressMatcher states:

a matcher which is configured with an IPv4 address will never match a request which returns an IPv6 address, and vice-versa.

The current implementation doesn't enforce this at the byte-array level:

byte[] remAddr = toCheck.getAddress();
byte[] reqAddr = this.requiredAddress.getAddress();
int nMaskFullBytes = this.nMaskBits / 8;
byte finalByte = (byte) (0xFF00 >> (this.nMaskBits & 0x07));
for (int i = 0; i < nMaskFullBytes; i++) {
    if (remAddr[i] != reqAddr[i]) {
        return false;
    }
}

There's no check that remAddr.length == reqAddr.length. If the configured CIDR mask requires more full bytes than the shorter of the two addresses has (e.g. an IPv6 /64 matcher checked against an IPv4 address), and the leading bytes happen to be equal up to the shorter array's length, the loop indexes past the end of the shorter array.

To Reproduce

IpAddressMatcher matcher = new IpAddressMatcher("2001:db8::/64");
// 32.1.13.184's bytes (0x20, 0x01, 0x0d, 0xb8) equal the first 4 bytes of 2001:0db8::,
// so the comparison loop doesn't short-circuit before running past the 4-byte array.
matcher.matches("32.1.13.184");

This throws:

java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
	at org.springframework.security.util.matcher.IpInetAddressMatcher.matches(IpInetAddressMatcher.java:100)

instead of returning false.

Expected behavior

matches() should return false when the two addresses belong to different families, per the documented contract, instead of throwing.

Sample

I have a fix ready (add a length check on the two byte arrays before comparing them) plus regression tests, and will open a PR referencing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions