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

subframe: turn panics into errors #10

Merged
merged 1 commit into from
Sep 17, 2015
Merged

Conversation

pmezard
Copy link
Contributor

@pmezard pmezard commented Sep 17, 2015

Hello,

I have run go-fuzz on the flac package and it eventually triggered panics by supplying invalid user inputs. I believe panics should be reserved to internal invariant violations or irrecoverable errors, not invalid user inputs, so this change turns them into errors.

I believe panics should be reserved to internal invariant violations or
irrecoverable errors, not invalid user inputs. Also, they are triggered
by go-fuzz, removing them helps testing the package.
@mewmew
Copy link
Member

mewmew commented Sep 17, 2015

Hi Patrick,

Thanks for spearheading this! I was very fascinated by go-fuzz when reading about it, and it provides a great tool for improving the robustness of packages. As you may have noticed from the panic messages, they all refer to specific parts of the FLAC spec which have not yet been implemented. The main reason is that I simply have not found any FLAC files which uses wasted-bits-per-sample, or are encoded with Rice parameter escape code. The negative shift may be a real issue (I cannot remember if those may occur in valid FLAC files) and should therefore return an error message.

If you were to stumble on regular FLAC files (i.e. music files generated by specific FLAC encoding parameters) which triggers any of these cases, I would be very interested in receiving a copy!

Once again, thanks for taking the initiative to run go-fuzz on the FLAC package. Do you by any chance have this code in a GitHub repo? It would be interesting to learn about how to hook up go-fuzz.

Cheers /u

mewmew added a commit that referenced this pull request Sep 17, 2015
subframe: turn panics into errors
@mewmew mewmew merged commit b115786 into mewkiz:master Sep 17, 2015
@pmezard
Copy link
Contributor Author

pmezard commented Sep 17, 2015

go-fuzz is a very interesting tool, which I randomly run on third-party packages to see what it can find and how fast. I have pushed my fuzzing branch here:

https://github.com/pmezard/flac-1/tree/fuzz

The two interesting bits are:

  • fuzz.go, implementing a very simple decoding routine taking an input byte array. go-fuzz README has more interesting examples.
  • corpus directory, containing all "interesting" inputs at the end of the 15mn run I did on your flac package. Note that ken.flac was the only one I put there myself, the others are generated by go-fuzz tool. The impressive bit is the fuzzing tool adjusts itself using coverage information and AST annotations.

To use it you have to do something like:

$ go get github.com/dvyukov/go-fuzz/go-fuzz
$ go get github.com/dvyukov/go-fuzz/go-fuzz-build
$ cd src/github.com/mewkiz/flac
$ go-fuzz-build github.com/mewkiz/flac
$ go-fuzz -bin=flac-fuzz.bin -workdir=.

This thing works well, and find problems quite fast. For instance, the last one before testing your package :

eaburns/flac#8

That said, running it on image/audio/video codecs often triggers issues with memory allocations which are not necessarily problems with the package. It could either panic upon overallocation (in eaburns case), or make the system swap like crazy (with your package).

@mewmew
Copy link
Member

mewmew commented Sep 17, 2015

Thanks a lot! I got a crash after only two minues, when running go-fuzz on the latest version of the code, including your fixes. Will be interesting to see what else it may uncover. Only sad part is that my computer completely freezes up when I run go-fuzz, so will have to wait until I have access to better hardware before running more tests.

The impressive bit is the fuzzing tool adjusts itself using coverage information and AST annotations.

I know, when I first read about it this felt like an impressively effective idea to guide the fuzzing. The combination of genetic algorithms for input generation and code coverage to track what has been tested, and which branches to take.

@karlek
Copy link
Contributor

karlek commented Sep 18, 2015

@mewmew, I can give it a try!

@mewmew
Copy link
Member

mewmew commented Sep 18, 2015

Nice!!! :)

@mewmew
Copy link
Member

mewmew commented Sep 18, 2015

@karlek, make sure to run on the latest version of the code.

go get gopkg.in/mewkiz/flac.v1 will pull version 1, which does not yet include this pull request. Use git clone github.com/mewkiz/flac, or simply bump the tag of this repo to v1.0.3 :) Your choice.

mewmew added a commit that referenced this pull request May 5, 2016
…3 release notes.

Updates #10.

(better late than never)
@mewmew mewmew added this to the v1.0.3 milestone Jul 25, 2016
@mewmew mewmew mentioned this pull request Aug 19, 2018
@karlek
Copy link
Contributor

karlek commented Jan 26, 2021

I finally got around fuzzing our own library.

As mentioned by @pmezard only out of memory panics gets triggered. These can be filtered out by checking the size before allocation. By returning an error for abnormally large allocations, we can fuzz relevant parts of the library.

After 8 hours of fuzzing on absolute-seek (#46) with a i7-6500U CPU @ 2.50GHz and the following patch, no crashes were found! 🎉

diff --git a/meta/picture.go b/meta/picture.go
index c0d7951..ff59e59 100644
--- a/meta/picture.go
+++ b/meta/picture.go
@@ -2,6 +2,7 @@ package meta
 
 import (
 	"encoding/binary"
+	"errors"
 	"io"
 )
 
@@ -66,6 +67,10 @@ func (block *Block) parsePicture() error {
 		return unexpected(err)
 	}
 
+	// 67108864 == 2**26 ~= 67 MiB
+	if x > 67108864 {
+		return errors.New("picture data too large")
+	}
 	// (MIME type length) bytes: MIME.
 	buf, err := readBytes(block.lr, int(x))
 	if err != nil {
@@ -78,6 +83,10 @@ func (block *Block) parsePicture() error {
 		return unexpected(err)
 	}
 
+	// 67108864 == 2**26 ~= 67 MiB
+	if x > 67108864 {
+		return errors.New("picture data too large")
+	}
 	// (description length) bytes: Desc.
 	buf, err = readBytes(block.lr, int(x))
 	if err != nil {
@@ -113,6 +122,10 @@ func (block *Block) parsePicture() error {
 		return nil
 	}
 
+	// 67108864 == 2**26 ~= 67 MiB
+	if x > 67108864 {
+		return errors.New("picture data too large")
+	}
 	// (data length) bytes: Data.
 	pic.Data = make([]byte, x)
 	_, err = io.ReadFull(block.lr, pic.Data)
diff --git a/meta/seektable.go b/meta/seektable.go
index c0b96ce..2a08b30 100644
--- a/meta/seektable.go
+++ b/meta/seektable.go
@@ -22,6 +22,9 @@ func (block *Block) parseSeekTable() error {
 	if n < 1 {
 		return errors.New("meta.Block.parseSeekTable: at least one seek point is required")
 	}
+	if n > 1000000 {
+		return errors.New("seektable too large")
+	}
 	table := &SeekTable{Points: make([]SeekPoint, n)}
 	block.Body = table
 	var prev uint64
diff --git a/meta/vorbiscomment.go b/meta/vorbiscomment.go
index 78935e3..f7d0e45 100644
--- a/meta/vorbiscomment.go
+++ b/meta/vorbiscomment.go
@@ -2,6 +2,7 @@ package meta
 
 import (
 	"encoding/binary"
+	"errors"
 	"fmt"
 	"strings"
 )
@@ -25,6 +26,10 @@ func (block *Block) parseVorbisComment() (err error) {
 		return unexpected(err)
 	}
 
+	// 67108864 == 2**26 ~= 67 MiB
+	if x > 67108864 {
+		return errors.New("vorbis comment data too large")
+	}
 	// (vendor length) bits: Vendor.
 	buf, err := readBytes(block.lr, int(x))
 	if err != nil {
@@ -49,6 +54,10 @@ func (block *Block) parseVorbisComment() (err error) {
 			return unexpected(err)
 		}
 
+		// 67108864 == 2**26 ~= 67 MiB
+		if x > 67108864 {
+			return errors.New("vorbis comment data too large")
+		}
 		// (vector length): vector.
 		buf, err = readBytes(block.lr, int(x))
 		if err != nil {

@mewmew
Copy link
Member

mewmew commented Jan 27, 2021

After 8 hours of fuzzing on absolute-seek (#46) with a i7-6500U CPU @ 2.50GHz and the following patch, no crashes were found! 🎉

Really cool to see you got around to fuzzing @karlek!

Du får visa lite på vår nästa weekend-hack :)

@mewmew mewmew mentioned this pull request Oct 4, 2022
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

Successfully merging this pull request may close these issues.

3 participants