Skip to content

Commit 95880d0

Browse files
authored
fix(ipaddress): use optional(hexGroupsPrefix) with + quantifier to handle zero-group IPv4-mapped IPv6
1 parent 6b1b896 commit 95880d0

1 file changed

Lines changed: 8 additions & 6 deletions

File tree

src/IPAddress.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,14 @@ const octet: Parser<number> = guard(
5959
// the quantifier requires hex digits — a second ":" causes backtracking.
6060
const hexChain = regex(/[0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4})*/, "hex-chain");
6161

62-
// Regex for zero or more hex groups each with a trailing colon, e.g. "ffff:a:".
62+
// Regex for one or more hex groups each with a trailing colon, e.g. "ffff:a:".
6363
// Used in IPv4-mapped IPv6 to match middle groups before the IPv4 suffix.
6464
// Unlike hexChain this stops as soon as the next group would not be followed
6565
// by ":" — so for "ffff:192.0.2.128" it matches only "ffff:" because "192."
66-
// has no trailing colon.
66+
// has no trailing colon. Wrapped with optional() in seq() to handle the
67+
// zero-group case (e.g. "::192.0.2.128").
6768
const hexGroupsPrefix = regex(
68-
/(?:[0-9a-fA-F]{1,4}:)*/,
69+
/(?:[0-9a-fA-F]{1,4}:)+/,
6970
"hex-groups-prefix",
7071
);
7172

@@ -213,17 +214,18 @@ export const IPAddress: DefinedLanguage<IPAddressOutputs> = defineLanguage<
213214
// ::192.0.2.128 (IPv4-compatible, deprecated but parseable)
214215
// 2001:db8::ffff:192.0.2.128
215216
//
216-
// The `hexGroupsPrefix` regex matches zero-or-more "hex:" tokens and stops
217+
// The `hexGroupsPrefix` regex matches one-or-more "hex:" tokens and stops
217218
// before the IPv4 octet because IPv4 octets are not followed by ":".
218219
// This prevents `hexChain` from greedily consuming "ffff:192" as two hex
219-
// groups and then failing on the trailing ".".
220+
// groups and then failing on the trailing ".". Wrapped with optional() to
221+
// handle the zero-group case (e.g. "::192.0.2.128").
220222
IPv6v4Mapped: (s) =>
221223
guard(
222224
map(
223225
seq(
224226
optional(hexChain), // optional leading hex groups before "::"
225227
str("::"),
226-
hexGroupsPrefix, // zero or more "hex:" groups before IPv4
228+
optional(hexGroupsPrefix), // zero or more "hex:" groups before IPv4
227229
s.IPv4, // IPv4 address occupying the last 32 bits
228230
),
229231
(_, b, a) => b.text.substring(b.index, a.index),

0 commit comments

Comments
 (0)