Skip to content

Commit

Permalink
fix: Decompressor to return -1 when output doesn't fit (#1022)
Browse files Browse the repository at this point in the history
* fix: Decompressor to return -1 when output doesn't fit

* docs explain "outBuffer too short" logic

* fix make staticcheck happy
  • Loading branch information
Tabaie authored Jan 26, 2024
1 parent 2fbf083 commit 179023d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 3 deletions.
8 changes: 5 additions & 3 deletions std/compress/lzss/snark.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
// it is on the caller to ensure that the dictionary is correct; in particular it must consist of bytes. Decompress does not check this.
// it is recommended to pack the dictionary using compress.Pack and take a MiMC checksum of it.
// d will consist of bytes
// It returns the length of d as a frontend.Variable
// It returns the length of d as a frontend.Variable; if the decompressed stream doesn't fit in d, dLength will be "-1"
func Decompress(api frontend.API, c []frontend.Variable, cLength frontend.Variable, d, dict []frontend.Variable, level lzss.Level) (dLength frontend.Variable, err error) {

// size-related "constants"
Expand Down Expand Up @@ -62,7 +62,7 @@ func Decompress(api frontend.API, c []frontend.Variable, cLength frontend.Variab
copyLen := frontend.Variable(0) // remaining length of the current copy
copyLen01 := frontend.Variable(1)
eof := frontend.Variable(0)
dLength = 0
dLength = -1 // if the following loop ends before hitting eof, we will get the "error" value -1 for dLength

for outI := range d {

Expand Down Expand Up @@ -114,7 +114,9 @@ func Decompress(api frontend.API, c []frontend.Variable, cLength frontend.Variab

eofNow := rangeChecker.IsLessThan(byteNbWords, api.Sub(cLength, inI)) // less than a byte left; meaning we are at the end of the input

dLength = api.Add(dLength, api.Mul(api.Sub(eofNow, eof), outI+1)) // if eof, don't advance dLength
// if eof, don't advance dLength
// if eof was JUST hit, dLength += outI + 2; so dLength = -1 + outI + 2 = outI + 1 which is the current output length
dLength = api.Add(dLength, api.Mul(api.Sub(eofNow, eof), outI+2))
eof = eofNow

}
Expand Down
41 changes: 41 additions & 0 deletions std/compress/lzss/snark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,31 @@ func Test3c2943withHeader(t *testing.T) {
test.NewAssert(t).CheckCircuit(circuit, test.WithValidAssignment(assignment), test.WithBackends(backend.PLONK), test.WithCurves(ecc.BLS12_377))
}

func TestOutBufTooShort(t *testing.T) {
const truncationAmount = 3
d := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9}
compressor, err := lzss.NewCompressor(nil, lzss.BestCompression)
require.NoError(t, err)
c, err := compressor.Compress(d)
require.NoError(t, err)

circuit := decompressionLengthTestCircuit{
C: make([]frontend.Variable, len(c)+inputExtraBytes),
D: make([]frontend.Variable, len(d)-truncationAmount), // not enough room

}

assignment := decompressionLengthTestCircuit{
C: test_vector_utils.ToVariableSlice(append(c, make([]byte, inputExtraBytes)...)),
CLength: len(c),
D: test_vector_utils.ToVariableSlice(d[:len(d)-truncationAmount]),
ExpectedDLength: -1,
}

RegisterHints()
test.NewAssert(t).CheckCircuit(&circuit, test.WithValidAssignment(&assignment), test.WithCurves(ecc.BLS12_377))
}

// Fuzz test the decompression
func Fuzz(f *testing.F) { // TODO This is always skipped
f.Fuzz(func(t *testing.T, input, dict []byte) {
Expand Down Expand Up @@ -179,3 +204,19 @@ func getDictionary() []byte {
}
return d
}

type decompressionLengthTestCircuit struct {
C, D []frontend.Variable
CLength frontend.Variable
ExpectedDLength frontend.Variable
}

func (c *decompressionLengthTestCircuit) Define(api frontend.API) error {
dict := test_vector_utils.ToVariableSlice(lzss.AugmentDict(nil))
if dLength, err := Decompress(api, c.C, c.CLength, c.D, dict, lzss.BestCompression); err != nil {
return err
} else {
api.AssertIsEqual(dLength, c.ExpectedDLength)
return nil
}
}

0 comments on commit 179023d

Please sign in to comment.