Skip to content

fix: pad Address6#toByteArray to a full 16 bytes#209

Open
spokodev wants to merge 1 commit into
beaugunderson:mainfrom
spokodev:fix/ipv6-tobytearray-length
Open

fix: pad Address6#toByteArray to a full 16 bytes#209
spokodev wants to merge 1 commit into
beaugunderson:mainfrom
spokodev:fix/ipv6-tobytearray-length

Conversation

@spokodev

Copy link
Copy Markdown

An IPv6 address is a 128-bit (16-octet) identifier per RFC 4291 §2, but Address6#toByteArray() and toUnsignedByteArray() return a variable-length array that drops high-order zero bytes:

new Address6("::1").toByteArray()                // [1]                      (expected 16 bytes)
new Address6("::").toByteArray()                 // [0]                      (expected 16 bytes)
new Address6("::ffff:192.168.0.1").toByteArray() // [255,255,192,168,0,1]    (expected 16 bytes)

The documented use is Buffer.from(address.toByteArray()), so for ::1 you get a 1-byte buffer instead of the 16-byte address. This breaks fixed-width consumers: socket/packet builders, DB BINARY(16)/inet columns (cf. #23), dedup/ACL byte comparisons, and any pre-sized buffer. It affects roughly half of all addresses (anything with a zero top byte: loopback, unspecified, link-local fe80::, ULA, documentation 2001:db8::, IPv4-mapped, NAT64).

Cause

bigInt().toString(16) drops leading zero nibbles. The existing leadingPad only restores odd-nibble parity (the fix for the length-17 case in #40), never whole zero bytes.

Fix

Pad the hex to BITS / 4 (32) nibbles, mirroring the existing binaryZeroPad() (toString(2).padStart(BITS, "0")) and the Address4#toArray sibling, which already returns a fixed-width array. fromByteArray/fromUnsignedByteArray already read big-endian, so round-tripping is unchanged.

Tests

Strengthened the existing round-trip assertions from length.should.be.at.most(16) to equal(16), and added focused cases for leading-zero addresses (::, ::1, ::ffff:192.168.0.1). These fail on the current code and pass with the fix; full suite green.

`bigInt().toString(16)` drops high-order zero nibbles, so `toByteArray()`
and `toUnsignedByteArray()` returned a short array for any address with
leading zero bytes. `::1` yielded `[1]` and `::` yielded `[0]` instead of
the documented 16-byte representation, which breaks `Buffer.from(...)` for
fixed-width network and storage use.

Pad the hex string to `BITS / 4` nibbles (16 bytes), matching the existing
`binaryZeroPad()` approach and the `Address4#toArray` sibling, which
already returns a fixed-width array.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant