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

Problems parsing binary blobs #62

Open
mhite opened this issue Aug 4, 2023 · 1 comment
Open

Problems parsing binary blobs #62

mhite opened this issue Aug 4, 2023 · 1 comment

Comments

@mhite
Copy link

mhite commented Aug 4, 2023

I am hitting an interesting error when parsing a binary blob.

Here's the code of interest:

func readBlob(reader *bufio.Reader) ([]byte, int, error) {
	// First, get the length
	var blobLen int32
	if err := binary.Read(reader, binary.BigEndian, &blobLen); err != nil {
		return nil, 0, err
	}
	n := 4 + int(blobLen)

	if blobLen < 1 || blobLen > int32(reader.Buffered()) {
		return nil, 0, fmt.Errorf("readBlob: invalid blob length %d", blobLen)
	}

	// Read the data
	blob := make([]byte, blobLen)
	if _, err := reader.Read(blob); err != nil {
		return nil, 0, err
	}

	// Remove the padding bytes
	numPadBytes := padBytesNeeded(int(blobLen))
	if numPadBytes > 0 {
		n += numPadBytes
		dummy := make([]byte, numPadBytes)
		if _, err := reader.Read(dummy); err != nil {
			return nil, 0, err
		}
	}

	return blob, n, nil
}

Specifically:

	if blobLen < 1 || blobLen > int32(reader.Buffered()) {
		return nil, 0, fmt.Errorf("readBlob: invalid blob length %d", blobLen)
	}

I am wondering reader.Buffered() is really returning the full length as expected.

For context, here's some debug logs I have from my application.

2023/08/04 11:09:10 Couldn't parse token
2023/08/04 11:09:10 err = readBlob: invalid blob length 11520
2023/08/04 11:09:10 token: ([]uint8) (len=11596 cap=16384) {
 00000000  23 62 75 6e 64 6c 65 00  00 00 00 00 00 00 00 01  |#bundle.........|
 00000010  00 00 2d 38 2f 53 74 61  74 75 73 2f 44 65 63 6b  |..-8/Status/Deck|
 00000020  2f 53 6f 6e 67 2f 4f 76  65 72 76 69 65 77 00 00  |/Song/Overview..|
 00000030  2c 69 69 69 69 62 00 00  00 00 00 00 00 00 00 f0  |,iiiib..........|
 00000040  00 00 00 10 00 00 00 03  00 00 2d 00 00 00 00 00  |..........-.....|
 00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00000070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
... truncated
 00002d20  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00002d30  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
 00002d40  00 00 00 00 00 00 00 00  00 00 00 00              |............|
}

The number of bytes in the token output you see above that appear before the blob is 76 bytes. The length of the token is 11596 (including those 76 bytes).

11596 - 76 = 11520

So, we can see that 11520 blob bytes are indeed present.

I think the problem might be that reader.Buffered() is not returning what you expect, ie. the full number of bytes in the buffered reader but rather just what you get from a single .Read() on the buffer. There might be a smaller buffer than 11520 bytes in use, and perhaps multiple reads are required?

Just a theory. I could be totally wrong... I can drop an actual payload from a packet capture somewhere if it helps.

@mhite
Copy link
Author

mhite commented Aug 4, 2023

I think the default buffer is 4096.

https://cs.opensource.google/go/go/+/master:src/bufio/bufio.go;l=19

Math adds up. I added some more info to the error message so we could see what .Buffered() equals.

err = readBlob: invalid blob length 11520, Buffered() == 4020

4020 + 76 bytes (see previous comment about the 76 byte present before the blob) = 4096.

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

1 participant