Skip to content

Commit

Permalink
capnp: avoid panics on invalid input (#139)
Browse files Browse the repository at this point in the history
This PR prevents code from panicking and fixes some small errors
during unpacking:

Prevents malformed input for composite lists to cause the pogs
library to panic.

Make the `packed.Decoder` throw an error if the input is `0x00`.
According to the spec, at least one more byte is required.

Make the `packet.Decoder` throw an error if the input for the
unpacked bytes (`0xFF` tag) does not contain enough unpacked bytes.

Additionally, update the go/gazelle rules and update the bazel version on CI.

Fixes #137
  • Loading branch information
oncilla authored and zombiezen committed May 5, 2019
1 parent e1ae1f9 commit 0c36f8f
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 19 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

CloudFlare Inc.
Daniel Darabos <[email protected]>
Dominik Roos <[email protected]>
Eran Duchan <[email protected]>
Evan Shaw <[email protected]>
Google Inc.
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
Alan Braithwaite <[email protected]>
Albert Strasheim <[email protected]>
Daniel Darabos <[email protected]>
Dominik Roos <[email protected]>
Eran Duchan <[email protected]>
Evan Shaw <[email protected]>
Ian Denhardt <[email protected]>
Expand Down
10 changes: 5 additions & 5 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
name = "io_bazel_rules_go",
sha256 = "8b68d0630d63d95dacc0016c3bb4b76154fe34fca93efd65d1c366de3fcb4294",
urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.12.1/rules_go-0.12.1.tar.gz"],
sha256 = "86ae934bd4c43b99893fc64be9d9fc684b81461581df7ea8fc291c816f5ee8c5",
urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.18.3/rules_go-0.18.3.tar.gz"],
)

http_archive(
name = "bazel_gazelle",
sha256 = "ddedc7aaeb61f2654d7d7d4fd7940052ea992ccdb031b8f9797ed143ac7e8d43",
urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/0.12.0/bazel-gazelle-0.12.0.tar.gz"],
sha256 = "3c681998538231a2d24d0c07ed5a7658cb72bfb5fd4bf9911157c0e9ac6a2687",
urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/0.17.0/bazel-gazelle-0.17.0.tar.gz"],
)

load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_rules_dependencies")
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")

go_rules_dependencies()

Expand Down
2 changes: 1 addition & 1 deletion _travis/install.bash
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ die() {
if [[ -z "$USE_BAZEL" || "$USE_BAZEL" -eq "0" ]]; then
must go get -t ./...
else
BAZEL_VERSION="${BAZEL_VERSION:-0.14.1}"
BAZEL_VERSION="${BAZEL_VERSION:-0.25.0}"
case "$TRAVIS_OS_NAME" in
linux)
BAZEL_INSTALLER_URL="https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh"
Expand Down
11 changes: 9 additions & 2 deletions capn.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ func (s *Segment) readListPtr(base Address, val rawPointer) (List, error) {
}
sz := hdr.structSize()
n := int32(hdr.offset())
if n < 0 {
return List{}, errListSize
}
// TODO(light): check that this has the same end address
if tsize, ok := sz.totalSize().times(n); !ok {
return List{}, errOverflow
Expand All @@ -214,19 +217,23 @@ func (s *Segment) readListPtr(base Address, val rawPointer) (List, error) {
flags: isCompositeList,
}, nil
}
n := val.numListElements()
if n < 0 {
return List{}, errListSize
}
if lt == bit1List {
return List{
seg: s,
off: addr,
length: val.numListElements(),
length: n,
flags: isBitList,
}, nil
}
return List{
seg: s,
size: val.elementSize(),
off: addr,
length: val.numListElements(),
length: n,
}, nil
}

Expand Down
23 changes: 13 additions & 10 deletions internal/packed/packed.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ func Unpack(dst, src []byte) ([]byte, error) {
dst = allocWords(dst, int(src[0]))
src = src[1:]
n := copy(dst[start:], src)
if n < len(dst)-start {
return dst, io.ErrUnexpectedEOF
}
src = src[n:]
}
}
Expand Down Expand Up @@ -281,22 +284,22 @@ func (r *Reader) ReadWord(p []byte) error {
switch tag {
case zeroTag:
z, err := r.rd.ReadByte()
if err == io.EOF {
r.err = io.ErrUnexpectedEOF
return nil
} else if err != nil {
if err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
r.err = err
return nil
return err
}
r.zeroes = int(z)
case unpackedTag:
l, err := r.rd.ReadByte()
if err == io.EOF {
r.err = io.ErrUnexpectedEOF
return nil
} else if err != nil {
if err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
r.err = err
return nil
return err
}
r.literal = int(l)
}
Expand Down
21 changes: 21 additions & 0 deletions internal/packed/packed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,27 @@ var badDecompressionTests = []struct {
name string
input []byte
}{
{
"short zero tag",
[]byte{0x00},
},
{
"short unpacked tag",
[]byte{0xFF},
},
{
"unpacked tag, only one word",
[]byte{
0xFF, 0, 0, 0, 0, 0, 0, 0, 0,
},
},
{
"unpacked tag, short unpacked word",
[]byte{
0xFF, 0, 0, 0, 0, 0, 0, 0, 0,
0x01, 0,
},
},
{
"wrong tag",
[]byte{
Expand Down
2 changes: 1 addition & 1 deletion pointer.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func (p Ptr) text() (b []byte, ok bool) {
// Text must be null-terminated.
return nil, false
}
return b[:len(b)-1 : len(b)], true
return b[: len(b)-1 : len(b)], true
}

// Data attempts to convert p into Data, returning nil if p is not a
Expand Down

0 comments on commit 0c36f8f

Please sign in to comment.