Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid masks cause panic #1

Open
parsiya opened this issue Apr 29, 2018 · 0 comments
Open

Invalid masks cause panic #1

parsiya opened this issue Apr 29, 2018 · 0 comments
Assignees

Comments

@parsiya
Copy link

parsiya commented Apr 29, 2018

This minimal example for 10.0.0.0/40

package main

import (
	"github.com/malfunkt/iprange"
)

func main() {
	_, _ = iprange.ParseList("10.0.0.0/40")
}

results in a panic:

$ go run test1.go
panic: runtime error: index out of range

goroutine 1 [running]:
encoding/binary.binary.bigEndian.Uint32(...)
        Go/src/encoding/binary/binary.go:111
github.com/malfunkt/iprange.(*ipParserImpl).Parse(0xc04209e000, 0x500ba0, 0xc04209c050, 0x0)
        yaccpar:355 +0x2007
github.com/malfunkt/iprange.ipParse(0x500ba0, 0xc04209c050, 0xb)
        yaccpar:153 +0x5f
github.com/malfunkt/iprange.ParseList(0x4ec90f, 0xb, 0x0, 0x0, 0x4b2533, 0xc042085f78, 0xc042054058)
        ip.y:93 +0xbe
main.main()
        test1.go:8 +0x3d
exit status 2

With an invalid mask, the mask variable coming from net.CIDRMask at https://github.com/malfunkt/iprange/blob/master/y.go#L502 is nil:

case 5:
  ipDollar = ipS[ippt-3 : ippt+1]
  //line ip.y:54
  {
    mask := net.CIDRMask(int(ipDollar[3].num), 32) // mask == nil if original mask is invalid
    min := ipDollar[1].addrRange.Min.Mask(mask)   // min == nil in this case too
    maxInt := binary.BigEndian.Uint32([]byte(min)) +
      0xffffffff -
      binary.BigEndian.Uint32([]byte(mask)) // nil passed to Uint32 causes a panic 
    maxBytes := make([]byte, 4)

Passing a nil or short byte[] to `Uint32 results in a panic. The bounds check hint which causes the panic can be seen here:

func (bigEndian) Uint32(b []byte) uint32 {
  _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
  return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
}

Solution

I am not very familiar with the codebase so these might be way off.

  • Quick: Check mask' and minvalues in [y.go#L502](https://github.com/malfunkt/iprange/blob/master/y.go#L502) before passing it toUint32`
  • Not quick but IMO better solution: Check input for validity before passing it down. For example check if mask value is valid (16-30 if I am not mistaken).
@arturovm arturovm self-assigned this May 18, 2018
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

No branches or pull requests

2 participants