From 1663a8a2f5f6df05d6de363d1b51408b892bd5b6 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Sun, 8 Mar 2015 17:43:44 +1100 Subject: [PATCH] iplist: Fix ranges that contain extra colons, and minimize memory use for IP --- iplist/iplist.go | 16 ++++++++++++-- iplist/iplist_test.go | 51 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/iplist/iplist.go b/iplist/iplist.go index d04b0905..5585909b 100644 --- a/iplist/iplist.go +++ b/iplist/iplist.go @@ -77,6 +77,13 @@ func (me *IPList) lookup(ip net.IP) (r *Range) { return } +func minifyIP(ip *net.IP) { + v4 := ip.To4() + if v4 != nil { + *ip = append(make([]byte, 0, 4), v4...) + } +} + // Parse a line of the PeerGuardian Text Lists (P2P) Format. Returns !ok but // no error if a line doesn't contain a range but isn't erroneous, such as // comment and blank lines. @@ -85,7 +92,9 @@ func ParseBlocklistP2PLine(l []byte) (r Range, ok bool, err error) { if len(l) == 0 || bytes.HasPrefix(l, []byte("#")) { return } - colon := bytes.IndexByte(l, ':') + // TODO: Something tells me this will end badly when IPv6 blocklists are + // added. + colon := bytes.LastIndexAny(l, ":") if colon == -1 { err = errors.New("missing colon") return @@ -98,8 +107,11 @@ func ParseBlocklistP2PLine(l []byte) (r Range, ok bool, err error) { hyphen += colon + 1 r.Description = string(l[:colon]) r.First = net.ParseIP(string(l[colon+1 : hyphen])) + minifyIP(&r.First) r.Last = net.ParseIP(string(l[hyphen+1:])) - if r.First == nil || r.Last == nil { + minifyIP(&r.Last) + if r.First == nil || r.Last == nil || len(r.First) != len(r.Last) { + err = errors.New("bad IP range") return } ok = true diff --git a/iplist/iplist_test.go b/iplist/iplist_test.go index 08f5b80f..6b8ff1f0 100644 --- a/iplist/iplist_test.go +++ b/iplist/iplist_test.go @@ -2,23 +2,43 @@ package iplist import ( "bufio" + "fmt" "net" "strings" "testing" + + "github.com/bradfitz/iter" + + "bitbucket.org/anacrolix/go.torrent/util" ) var sample = ` # List distributed by iblocklist.com a:1.2.4.0-1.2.4.255 -b:1.2.8.0-1.2.8.255` +b:1.2.8.0-1.2.8.255 +something:more detail:86.59.95.195-86.59.95.195` + +func TestIPv4RangeLen(t *testing.T) { + ranges, _ := sampleRanges(t) + for i := range iter.N(3) { + if len(ranges[i].First) != 4 { + t.FailNow() + } + if len(ranges[i].Last) != 4 { + t.FailNow() + } + } +} func sampleRanges(tb testing.TB) (ranges []Range, err error) { scanner := bufio.NewScanner(strings.NewReader(sample)) for scanner.Scan() { - r, ok, _ := ParseBlocklistP2PLine(scanner.Bytes()) + r, ok, err := ParseBlocklistP2PLine(scanner.Bytes()) + if err != nil { + tb.Fatal(err) + } if ok { - // tb.Log(r) ranges = append(ranges, r) } } @@ -32,13 +52,34 @@ func BenchmarkParseP2pBlocklist(b *testing.B) { } } +func connRemoteAddrIP(network, laddr string, dialHost string) net.IP { + l, err := net.Listen(network, laddr) + if err != nil { + panic(err) + } + go func() { + c, err := net.Dial(network, net.JoinHostPort(dialHost, fmt.Sprintf("%d", util.AddrPort(l.Addr())))) + if err != nil { + panic(err) + } + defer c.Close() + }() + c, err := l.Accept() + if err != nil { + panic(err) + } + defer c.Close() + ret := util.AddrIP(c.RemoteAddr()) + return ret +} + func TestSimple(t *testing.T) { ranges, err := sampleRanges(t) if err != nil { t.Fatal(err) } - if len(ranges) != 2 { - t.Fatalf("expected 2 ranges but got %d", len(ranges)) + if len(ranges) != 3 { + t.Fatalf("expected 3 ranges but got %d", len(ranges)) } iplist := New(ranges) for _, _case := range []struct { -- 2.48.1