4kills/go-libdeflate

deadly data example

fufuok opened this issue · 7 comments

package main

import (
	"bytes"
	"compress/zlib"
	"encoding/hex"
	"fmt"
	"log"

	"github.com/4kills/go-libdeflate/v2"
	czlib "github.com/4kills/go-zlib"
)

var (
	s = "789c7d90316f83301085f7fc0ac45cac3b1b63cc0685542c55a4264b1784825bd1024686284851fe7b8104c454c" +
		"b8bdff7de9def6e3b6b3cf6db298dedc0b26f02384014858efb2af78ecb1573c224e24e92301e4919d158c0dd7e7" +
		"9a40a5de765f39ed76aca2e6a364caf5a17cacdbe2a7dcd8c6ab5e9d790eafab49d2ce87ac4f308724a5c5c70553" +
		"6bfe1b93f968fa214287570bcfc882c6034a0fc736bfde873f38f99aee666fccfb3ad0f043d4604122917dc1abdc" +
		"c6178deaa81a8416d60afcfba9ae8293e2cf2a5536609753f04194881be106c1de6d2eec7058c9c3180cdfc87691" +
		"f814505305c77796d9e66042e372dd2622ec001c143ff09bec7bea151f90c05f3e916cc22f57cc976f73fc74374"
	comp, _ = hex.DecodeString(s)
)

func main() {
	deWithZlib()       // nice, return error
	deWithLibdeflate() // hang, endless loop
	deWithCgoZlib()    // hang, endless loop
}

func deWithLibdeflate() {
	dc, _ := libdeflate.NewDecompressor()
	_, decompressed, err := dc.Decompress(comp, nil, libdeflate.ModeZlib)
	if err != nil {
		log.Println("deWithLibdeflate", err)
		return
	}
	fmt.Println(decompressed)
	dc.Close()
}

func deWithCgoZlib() {
	dc, _ := czlib.NewReader(nil)
	_, decompressed, err := dc.ReadBuffer(comp, nil)
	if err != nil {
		log.Println("deWithCgoZlib", err)
		return
	}
	fmt.Println(decompressed)
	_ = dc.Close()
}

func deWithZlib() {
	var decompressed bytes.Buffer
	dc, _ := zlib.NewReader(bytes.NewReader(comp))
	_, err := decompressed.ReadFrom(dc)
	if err != nil {
		log.Println("deWithZlib", err) // unexpected EOF
		return
	}
	fmt.Println(decompressed)
	_ = dc.Close()
}

Thank you for your issue. I am very sorry you had to experience this. I have a hunch about what might be the issue. I will look into it tonight.
Can you please provide the exact error message you get from compress/zlib and the Go version used?

root@DevBeta:~/go/zlib# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.1 LTS
Release:        20.04
Codename:       focal
root@DevBeta:~/go/zlib# go version
go version go1.19.4 linux/amd64
root@DevBeta:~/go/zlib# cat go.mod
module gozlib

go 1.17

require (
        github.com/4kills/go-libdeflate/v2 v2.0.2
        github.com/4kills/go-zlib v1.1.1
)
root@DevBeta:~/go/zlib# go build
root@DevBeta:~/go/zlib# ./gozlib 
2022/12/15 17:15:14 deWithZlib unexpected EOF
////// No response //////

top

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                                           
 448656 root      20   0 1298452  33352   2532 R 108.6   0.4   0:55.42 gozlib  

@fufuok What did you provide as deadly data exactly?
I have indentified the issue which is that the program keeps allocating more memory for storing the uncompressed data since the deflate algorithm has not enough output space.

The underlying problem is within the C library (libdeflate by ebiggers) used by this project. The C library does not give a more nuanced error message, so I will probably open an issue over there. Tomorrow I will provide a temporary fix until the issue with the C library is resolved

Maybe the title is a bit misleading, sorry for the trouble.

What I mean is: an illegal data will cause the program to not work properly.

The above sample data is obtained in our production, resulting in high memory usage. After investigation, it was found that it was caused by go-zlib, so I made this demo for you.

Thanks for your quick response, hope it gets better and better.

I have hot fixed it for now. It should work again. I will also create an issue over at the libdeflate c library to figure out the root cause.
@fufuok Is the input you provided trusted? If this was provided by a user this could potentially be a DOS type attack at your systems.

Please just update to the latest version of libdeflate, instead of implementing workarounds for issues in older versions.

Also be aware that DEFLATE streams can legitimately decompress to up to 1032x their original size. Decompressing with an unknown output size with no limit should be avoided when possible.