ref: e0efab37a8bbd245e60c9adffaba4182aeb17c87
parent: 026a628d0ebce3d347322d629031d0fdc93308bf
author: Frank Smit <frank@61924.nl>
date: Sun Aug 30 09:39:54 EDT 2020
Fix IPv6 parsing. 2001:b88:1202::10 resulted in [32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] while it should be [32, 1, 11, 136, 18, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16]
--- a/lib/std/ipparse.myr
+++ b/lib/std/ipparse.myr
@@ -52,21 +52,24 @@
;;
}
+const ipv6seg = 8
+
const ip6parse = {ip
var val : byte[16]
- var expand, split
+ var expand
var v, ok
- var i, nseg
+ var nseg, segsplit
ok = true
expand = false
- split = 0
+ segsplit = 0
+
if ip.len > 2 && eq(ip[:2], "::")
expand = true
- split = 0
;;
+
nseg = 0
- for i = 0; ip.len > 0 && ok; i++
+ for var i = 0; ip.len > 0 && ok; i++
/* parse 'num' segment */
(v, ip, ok) = num(ip, 0, 65536, 16, ':', ok)
@@ -75,7 +78,7 @@
val[i*2 + 1] = (v & 0xff : byte)
nseg++
- if ip.len == 0 || nseg == 8
+ if ip.len == 0 || nseg == ipv6seg
break
;;
@@ -84,14 +87,14 @@
if ip.len > 0 && ip[0] == (':' : byte) && !expand
(ip, ok) = delim(ip, ':', ok)
expand = true
- split = i
+ segsplit = nseg
;;
;;
if ok && ip.len == 0
if expand
- expandsplit(val[:], split, i)
- elif nseg != 8
+ expandsplit(val[:], nseg, segsplit)
+ elif nseg != ipv6seg
-> `None
;;
-> `Some `Ipv6 val
@@ -101,12 +104,17 @@
}
/* take "a:b::c:d" and expand it to "a:b:0:0:...:0:c:d" */
-const expandsplit = {ip, split, len
- var width
+const expandsplit = {ip, nseg, segsplit
+ var head, tail
+ var split, middle
- width = 16 - len
- std.slcp(ip[split:len], ip[split+width:len+width])
- std.slfill(ip[len:len+width], 0)
+ split = segsplit * 2
+ middle = (ipv6seg - nseg) * 2
+ head = ip[:split]
+ tail = ip[split : ip.len - middle]
+
+ std.slcp(ip[ip.len - tail.len:], tail)
+ std.slfill(ip[head.len : ip.len - tail.len], 0)
}
const delim = {ip, sep, ok
--- a/lib/std/test/ipparse.myr
+++ b/lib/std/test/ipparse.myr
@@ -52,6 +52,12 @@
0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00])
+ eq("2001:b88:1202::10", \
+ `std.Some `std.Ipv6 [ \
+ 0x20, 0x01, 0x0b, 0x88, \
+ 0x12, 0x02, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x10])
/* invalid ipv4 addresses */
eq("2a03:2880:2110:df07:face:b00c:0:1:abc", `std.None) /* too long */