Created
July 18, 2016 19:56
-
-
Save ajkeeton/87352777b8f458b05f363fe8cd73803c to your computer and use it in GitHub Desktop.
Permessage-deflate issue with Go's deflate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"compress/flate" | |
"encoding/hex" | |
"fmt" | |
"io" | |
"io/ioutil" | |
// "bufio" | |
"bytes" | |
"os" | |
"time" | |
) | |
func main() { | |
gonuts_permessage_poc() // <--- doesn't work | |
//gonuts_readall_poc() // <--- works | |
} | |
var magic_seperator = []byte{'\r', '\n', '\r', '\n'} | |
func gonuts_readall_poc() { | |
f, err := os.Open("flate_log.d") | |
if err != nil { | |
panic(err) | |
} | |
buf := bytes.NewBuffer(nil) | |
_, err = buf.ReadFrom(f) | |
if err != nil { | |
panic(err) | |
} | |
messages := bytes.Split(buf.Bytes(), magic_seperator) | |
fmt.Printf("Messages: %d\n", len(messages)) | |
compData := bytes.NewBuffer(nil) | |
deflater := flate.NewReader(compData) | |
// Unsplit into a single contiguous stream | |
for _, msg := range messages { | |
// msg is a single websockets message | |
compData.Write(msg) | |
} | |
decompressed, err := ioutil.ReadAll(deflater) | |
fmt.Printf("Err: %v. Decompressed:\n%s\n\n", err, hex.Dump(decompressed[0:len(decompressed)])) | |
} | |
func gonuts_permessage_poc() { | |
f, err := os.Open("flate_log.d") | |
if err != nil { | |
panic(err) | |
} | |
buf := bytes.NewBuffer(nil) | |
_, err = buf.ReadFrom(f) | |
if err != nil { | |
panic(err) | |
} | |
messages := bytes.Split(buf.Bytes(), magic_seperator) | |
fmt.Printf("Messages: %d\n", len(messages)) | |
compData := bytes.NewBuffer(nil) | |
deflater := flate.NewReader(compData) | |
for _, msg := range messages { | |
// msg is a single websockets message | |
compData.Write(msg) | |
decompressed, err := ioutil.ReadAll(deflater) | |
fmt.Printf("Err: %v. Decompressed:\n%s\n\n", err, hex.Dump(decompressed[0:len(decompressed)])) | |
if err == io.ErrUnexpectedEOF { | |
// Interestingly, ignoring an unexpected EOF allows more messages to be decompressed | |
// provided we use Reset here: | |
deflater.(flate.Resetter).Reset(compData, nil) | |
continue | |
} | |
if err != nil { | |
break | |
} | |
compData.Reset() | |
time.Sleep(1 * time.Second) | |
} | |
} |
Data was collected by dumping the payload from a series of compressed websockets messages (after appending 0x00 0x00 0xff 0xff) to a file and adding an arbitrary separater (CRLFCRLF). The traffic used permessage-deflate. The separater is used to split out the individual messages in the proof of concept code above to simulate the scenario.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sample data: https://dl.dropboxusercontent.com/u/15643648/flate_log.d