diff options
author | Slack Coder <slackcoder@server.ky> | 2023-10-18 17:27:00 -0500 |
---|---|---|
committer | Slack Coder <slackcoder@server.ky> | 2023-10-18 17:27:00 -0500 |
commit | 2be3a82f3a801a84c98a4de9c818ce8b0497135b (patch) | |
tree | 9fb89a6b10fddbb1560d895215b445813d3ea28c /vendor/github.com/xi2/xz/dec_stream.go | |
parent | 2fda2161877e61e16b7f208ba1f92f650776cbe2 (diff) | |
download | pkgtools-go-todo.tar.xz |
move todos to project roottodo
Diffstat (limited to 'vendor/github.com/xi2/xz/dec_stream.go')
-rw-r--r-- | vendor/github.com/xi2/xz/dec_stream.go | 932 |
1 files changed, 0 insertions, 932 deletions
diff --git a/vendor/github.com/xi2/xz/dec_stream.go b/vendor/github.com/xi2/xz/dec_stream.go deleted file mode 100644 index 9381a3c..0000000 --- a/vendor/github.com/xi2/xz/dec_stream.go +++ /dev/null @@ -1,932 +0,0 @@ -/* - * .xz Stream decoder - * - * Author: Lasse Collin <lasse.collin@tukaani.org> - * - * Translation to Go: Michael Cross <https://github.com/xi2> - * - * This file has been put into the public domain. - * You can do whatever you want with this file. - */ - -package xz - -import ( - "bytes" - "crypto/sha256" - "hash" - "hash/crc32" - "hash/crc64" -) - -/* from linux/lib/xz/xz_stream.h **************************************/ - -/* - * See the .xz file format specification at - * http://tukaani.org/xz/xz-file-format.txt - * to understand the container format. - */ -const ( - streamHeaderSize = 12 - headerMagic = "\xfd7zXZ\x00" - footerMagic = "YZ" -) - -/* - * Variable-length integer can hold a 63-bit unsigned integer or a special - * value indicating that the value is unknown. - */ -type vliType uint64 - -const ( - vliUnknown vliType = ^vliType(0) - /* Maximum encoded size of a VLI */ - vliBytesMax = 8 * 8 / 7 // (Sizeof(vliType) * 8 / 7) -) - -/* from linux/lib/xz/xz_dec_stream.c **********************************/ - -/* Hash used to validate the Index field */ -type xzDecHash struct { - unpadded vliType - uncompressed vliType - sha256 hash.Hash -} - -// type of xzDec.sequence -type xzDecSeq int - -const ( - seqStreamHeader xzDecSeq = iota - seqBlockStart - seqBlockHeader - seqBlockUncompress - seqBlockPadding - seqBlockCheck - seqIndex - seqIndexPadding - seqIndexCRC32 - seqStreamFooter -) - -// type of xzDec.index.sequence -type xzDecIndexSeq int - -const ( - seqIndexCount xzDecIndexSeq = iota - seqIndexUnpadded - seqIndexUncompressed -) - -/** - * xzDec - Opaque type to hold the XZ decoder state - */ -type xzDec struct { - /* Position in decMain */ - sequence xzDecSeq - /* Position in variable-length integers and Check fields */ - pos int - /* Variable-length integer decoded by decVLI */ - vli vliType - /* Saved inPos and outPos */ - inStart int - outStart int - /* CRC32 checksum hash used in Index */ - crc32 hash.Hash - /* Hashes used in Blocks */ - checkCRC32 hash.Hash - checkCRC64 hash.Hash - checkSHA256 hash.Hash - /* for checkTypes CRC32/CRC64/SHA256, check is one of the above 3 hashes */ - check hash.Hash - /* Embedded stream header struct containing CheckType */ - *Header - /* - * True if the next call to xzDecRun is allowed to return - * xzBufError. - */ - allowBufError bool - /* Information stored in Block Header */ - blockHeader struct { - /* - * Value stored in the Compressed Size field, or - * vliUnknown if Compressed Size is not present. - */ - compressed vliType - /* - * Value stored in the Uncompressed Size field, or - * vliUnknown if Uncompressed Size is not present. - */ - uncompressed vliType - /* Size of the Block Header field */ - size int - } - /* Information collected when decoding Blocks */ - block struct { - /* Observed compressed size of the current Block */ - compressed vliType - /* Observed uncompressed size of the current Block */ - uncompressed vliType - /* Number of Blocks decoded so far */ - count vliType - /* - * Hash calculated from the Block sizes. This is used to - * validate the Index field. - */ - hash xzDecHash - } - /* Variables needed when verifying the Index field */ - index struct { - /* Position in decIndex */ - sequence xzDecIndexSeq - /* Size of the Index in bytes */ - size vliType - /* Number of Records (matches block.count in valid files) */ - count vliType - /* - * Hash calculated from the Records (matches block.hash in - * valid files). - */ - hash xzDecHash - } - /* - * Temporary buffer needed to hold Stream Header, Block Header, - * and Stream Footer. The Block Header is the biggest (1 KiB) - * so we reserve space according to that. bufArray has to be aligned - * to a multiple of four bytes; the variables before it - * should guarantee this. - */ - temp struct { - pos int - buf []byte // slice buf will be backed by bufArray - bufArray [1024]byte - } - // chain is the function (or to be more precise, closure) which - // does the decompression and will call into the lzma2 and other - // filter code as needed. It is constructed by decBlockHeader - chain func(b *xzBuf) xzRet - // lzma2 holds the state of the last filter (which must be LZMA2) - lzma2 *xzDecLZMA2 - // pointers to allocated BCJ/Delta filters - bcjs []*xzDecBCJ - deltas []*xzDecDelta - // number of currently in use BCJ/Delta filters from the above - bcjsUsed int - deltasUsed int -} - -/* Sizes of the Check field with different Check IDs */ -var checkSizes = [...]byte{ - 0, - 4, 4, 4, - 8, 8, 8, - 16, 16, 16, - 32, 32, 32, - 64, 64, 64, -} - -/* - * Fill s.temp by copying data starting from b.in[b.inPos]. Caller - * must have set s.temp.pos to indicate how much data we are supposed - * to copy into s.temp.buf. Return true once s.temp.pos has reached - * len(s.temp.buf). - */ -func fillTemp(s *xzDec, b *xzBuf) bool { - copySize := len(b.in) - b.inPos - tempRemaining := len(s.temp.buf) - s.temp.pos - if copySize > tempRemaining { - copySize = tempRemaining - } - copy(s.temp.buf[s.temp.pos:], b.in[b.inPos:]) - b.inPos += copySize - s.temp.pos += copySize - if s.temp.pos == len(s.temp.buf) { - s.temp.pos = 0 - return true - } - return false -} - -/* Decode a variable-length integer (little-endian base-128 encoding) */ -func decVLI(s *xzDec, in []byte, inPos *int) xzRet { - var byte byte - if s.pos == 0 { - s.vli = 0 - } - for *inPos < len(in) { - byte = in[*inPos] - *inPos++ - s.vli |= vliType(byte&0x7f) << uint(s.pos) - if byte&0x80 == 0 { - /* Don't allow non-minimal encodings. */ - if byte == 0 && s.pos != 0 { - return xzDataError - } - s.pos = 0 - return xzStreamEnd - } - s.pos += 7 - if s.pos == 7*vliBytesMax { - return xzDataError - } - } - return xzOK -} - -/* - * Decode the Compressed Data field from a Block. Update and validate - * the observed compressed and uncompressed sizes of the Block so that - * they don't exceed the values possibly stored in the Block Header - * (validation assumes that no integer overflow occurs, since vliType - * is uint64). Update s.check if presence of the CRC32/CRC64/SHA256 - * field was indicated in Stream Header. - * - * Once the decoding is finished, validate that the observed sizes match - * the sizes possibly stored in the Block Header. Update the hash and - * Block count, which are later used to validate the Index field. - */ -func decBlock(s *xzDec, b *xzBuf) xzRet { - var ret xzRet - s.inStart = b.inPos - s.outStart = b.outPos - ret = s.chain(b) - s.block.compressed += vliType(b.inPos - s.inStart) - s.block.uncompressed += vliType(b.outPos - s.outStart) - /* - * There is no need to separately check for vliUnknown since - * the observed sizes are always smaller than vliUnknown. - */ - if s.block.compressed > s.blockHeader.compressed || - s.block.uncompressed > s.blockHeader.uncompressed { - return xzDataError - } - switch s.CheckType { - case CheckCRC32, CheckCRC64, CheckSHA256: - _, _ = s.check.Write(b.out[s.outStart:b.outPos]) - } - if ret == xzStreamEnd { - if s.blockHeader.compressed != vliUnknown && - s.blockHeader.compressed != s.block.compressed { - return xzDataError - } - if s.blockHeader.uncompressed != vliUnknown && - s.blockHeader.uncompressed != s.block.uncompressed { - return xzDataError - } - s.block.hash.unpadded += - vliType(s.blockHeader.size) + s.block.compressed - s.block.hash.unpadded += vliType(checkSizes[s.CheckType]) - s.block.hash.uncompressed += s.block.uncompressed - var buf [2 * 8]byte // 2*Sizeof(vliType) - putLE64(uint64(s.block.hash.unpadded), buf[:]) - putLE64(uint64(s.block.hash.uncompressed), buf[8:]) - _, _ = s.block.hash.sha256.Write(buf[:]) - s.block.count++ - } - return ret -} - -/* Update the Index size and the CRC32 hash. */ -func indexUpdate(s *xzDec, b *xzBuf) { - inUsed := b.inPos - s.inStart - s.index.size += vliType(inUsed) - _, _ = s.crc32.Write(b.in[s.inStart : s.inStart+inUsed]) -} - -/* - * Decode the Number of Records, Unpadded Size, and Uncompressed Size - * fields from the Index field. That is, Index Padding and CRC32 are not - * decoded by this function. - * - * This can return xzOK (more input needed), xzStreamEnd (everything - * successfully decoded), or xzDataError (input is corrupt). - */ -func decIndex(s *xzDec, b *xzBuf) xzRet { - var ret xzRet - for { - ret = decVLI(s, b.in, &b.inPos) - if ret != xzStreamEnd { - indexUpdate(s, b) - return ret - } - switch s.index.sequence { - case seqIndexCount: - s.index.count = s.vli - /* - * Validate that the Number of Records field - * indicates the same number of Records as - * there were Blocks in the Stream. - */ - if s.index.count != s.block.count { - return xzDataError - } - s.index.sequence = seqIndexUnpadded - case seqIndexUnpadded: - s.index.hash.unpadded += s.vli - s.index.sequence = seqIndexUncompressed - case seqIndexUncompressed: - s.index.hash.uncompressed += s.vli - var buf [2 * 8]byte // 2*Sizeof(vliType) - putLE64(uint64(s.index.hash.unpadded), buf[:]) - putLE64(uint64(s.index.hash.uncompressed), buf[8:]) - _, _ = s.index.hash.sha256.Write(buf[:]) - s.index.count-- - s.index.sequence = seqIndexUnpadded - } - if !(s.index.count > 0) { - break - } - } - return xzStreamEnd -} - -/* - * Validate that the next 4 bytes match s.crc32.Sum(nil). s.pos must - * be zero when starting to validate the first byte. - */ -func crcValidate(s *xzDec, b *xzBuf) xzRet { - sum := s.crc32.Sum(nil) - // CRC32 - reverse slice - sum[0], sum[1], sum[2], sum[3] = sum[3], sum[2], sum[1], sum[0] - for { - if b.inPos == len(b.in) { - return xzOK - } - if sum[s.pos] != b.in[b.inPos] { - return xzDataError - } - b.inPos++ - s.pos++ - if !(s.pos < 4) { - break - } - } - s.crc32.Reset() - s.pos = 0 - return xzStreamEnd -} - -/* - * Validate that the next 4/8/32 bytes match s.check.Sum(nil). s.pos - * must be zero when starting to validate the first byte. - */ -func checkValidate(s *xzDec, b *xzBuf) xzRet { - sum := s.check.Sum(nil) - if s.CheckType == CheckCRC32 || s.CheckType == CheckCRC64 { - // CRC32/64 - reverse slice - for i, j := 0, len(sum)-1; i < j; i, j = i+1, j-1 { - sum[i], sum[j] = sum[j], sum[i] - } - } - for { - if b.inPos == len(b.in) { - return xzOK - } - if sum[s.pos] != b.in[b.inPos] { - return xzDataError - } - b.inPos++ - s.pos++ - if !(s.pos < len(sum)) { - break - } - } - s.check.Reset() - s.pos = 0 - return xzStreamEnd -} - -/* - * Skip over the Check field when the Check ID is not supported. - * Returns true once the whole Check field has been skipped over. - */ -func checkSkip(s *xzDec, b *xzBuf) bool { - for s.pos < int(checkSizes[s.CheckType]) { - if b.inPos == len(b.in) { - return false - } - b.inPos++ - s.pos++ - } - s.pos = 0 - return true -} - -/* polynomial table used in decStreamHeader below */ -var xzCRC64Table = crc64.MakeTable(crc64.ECMA) - -/* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */ -func decStreamHeader(s *xzDec) xzRet { - if string(s.temp.buf[:len(headerMagic)]) != headerMagic { - return xzFormatError - } - if crc32.ChecksumIEEE(s.temp.buf[len(headerMagic):len(headerMagic)+2]) != - getLE32(s.temp.buf[len(headerMagic)+2:]) { - return xzDataError - } - if s.temp.buf[len(headerMagic)] != 0 { - return xzOptionsError - } - /* - * Of integrity checks, we support none (Check ID = 0), - * CRC32 (Check ID = 1), CRC64 (Check ID = 4) and SHA256 (Check ID = 10) - * However, we will accept other check types too, but then the check - * won't be verified and a warning (xzUnsupportedCheck) will be given. - */ - s.CheckType = CheckID(s.temp.buf[len(headerMagic)+1]) - if s.CheckType > checkMax { - return xzOptionsError - } - switch s.CheckType { - case CheckNone: - // CheckNone: no action needed - case CheckCRC32: - if s.checkCRC32 == nil { - s.checkCRC32 = crc32.NewIEEE() - } else { - s.checkCRC32.Reset() - } - s.check = s.checkCRC32 - case CheckCRC64: - if s.checkCRC64 == nil { - s.checkCRC64 = crc64.New(xzCRC64Table) - } else { - s.checkCRC64.Reset() - } - s.check = s.checkCRC64 - case CheckSHA256: - if s.checkSHA256 == nil { - s.checkSHA256 = sha256.New() - } else { - s.checkSHA256.Reset() - } - s.check = s.checkSHA256 - default: - return xzUnsupportedCheck - } - return xzOK -} - -/* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */ -func decStreamFooter(s *xzDec) xzRet { - if string(s.temp.buf[10:10+len(footerMagic)]) != footerMagic { - return xzDataError - } - if crc32.ChecksumIEEE(s.temp.buf[4:10]) != getLE32(s.temp.buf) { - return xzDataError - } - /* - * Validate Backward Size. Note that we never added the size of the - * Index CRC32 field to s->index.size, thus we use s->index.size / 4 - * instead of s->index.size / 4 - 1. - */ - if s.index.size>>2 != vliType(getLE32(s.temp.buf[4:])) { - return xzDataError - } - if s.temp.buf[8] != 0 || CheckID(s.temp.buf[9]) != s.CheckType { - return xzDataError - } - /* - * Use xzStreamEnd instead of xzOK to be more convenient - * for the caller. - */ - return xzStreamEnd -} - -/* Decode the Block Header and initialize the filter chain. */ -func decBlockHeader(s *xzDec) xzRet { - var ret xzRet - /* - * Validate the CRC32. We know that the temp buffer is at least - * eight bytes so this is safe. - */ - crc := getLE32(s.temp.buf[len(s.temp.buf)-4:]) - s.temp.buf = s.temp.buf[:len(s.temp.buf)-4] - if crc32.ChecksumIEEE(s.temp.buf) != crc { - return xzDataError - } - s.temp.pos = 2 - /* - * Catch unsupported Block Flags. - */ - if s.temp.buf[1]&0x3C != 0 { - return xzOptionsError - } - /* Compressed Size */ - if s.temp.buf[1]&0x40 != 0 { - if decVLI(s, s.temp.buf, &s.temp.pos) != xzStreamEnd { - return xzDataError - } - if s.vli >= 1<<63-8 { - // the whole block must stay smaller than 2^63 bytes - // the block header cannot be smaller than 8 bytes - return xzDataError - } - if s.vli == 0 { - // compressed size must be non-zero - return xzDataError - } - s.blockHeader.compressed = s.vli - } else { - s.blockHeader.compressed = vliUnknown - } - /* Uncompressed Size */ - if s.temp.buf[1]&0x80 != 0 { - if decVLI(s, s.temp.buf, &s.temp.pos) != xzStreamEnd { - return xzDataError - } - s.blockHeader.uncompressed = s.vli - } else { - s.blockHeader.uncompressed = vliUnknown - } - // get total number of filters (1-4) - filterTotal := int(s.temp.buf[1]&0x03) + 1 - // slice to hold decoded filters - filterList := make([]struct { - id xzFilterID - props uint32 - }, filterTotal) - // decode the non-last filters which cannot be LZMA2 - for i := 0; i < filterTotal-1; i++ { - /* Valid Filter Flags always take at least two bytes. */ - if len(s.temp.buf)-s.temp.pos < 2 { - return xzDataError - } - s.temp.pos += 2 - switch id := xzFilterID(s.temp.buf[s.temp.pos-2]); id { - case idDelta: - // delta filter - if s.temp.buf[s.temp.pos-1] != 0x01 { - return xzOptionsError - } - /* Filter Properties contains distance - 1 */ - if len(s.temp.buf)-s.temp.pos < 1 { - return xzDataError - } - props := uint32(s.temp.buf[s.temp.pos]) - s.temp.pos++ - filterList[i] = struct { - id xzFilterID - props uint32 - }{id: id, props: props} - case idBCJX86, idBCJPowerPC, idBCJIA64, - idBCJARM, idBCJARMThumb, idBCJSPARC: - // bcj filter - var props uint32 - switch s.temp.buf[s.temp.pos-1] { - case 0x00: - props = 0 - case 0x04: - if len(s.temp.buf)-s.temp.pos < 4 { - return xzDataError - } - props = getLE32(s.temp.buf[s.temp.pos:]) - s.temp.pos += 4 - default: - return xzOptionsError - } - filterList[i] = struct { - id xzFilterID - props uint32 - }{id: id, props: props} - default: - return xzOptionsError - } - } - /* - * decode the last filter which must be LZMA2 - */ - if len(s.temp.buf)-s.temp.pos < 2 { - return xzDataError - } - /* Filter ID = LZMA2 */ - if xzFilterID(s.temp.buf[s.temp.pos]) != idLZMA2 { - return xzOptionsError - } - s.temp.pos++ - /* Size of Properties = 1-byte Filter Properties */ - if s.temp.buf[s.temp.pos] != 0x01 { - return xzOptionsError - } - s.temp.pos++ - /* Filter Properties contains LZMA2 dictionary size. */ - if len(s.temp.buf)-s.temp.pos < 1 { - return xzDataError - } - props := uint32(s.temp.buf[s.temp.pos]) - s.temp.pos++ - filterList[filterTotal-1] = struct { - id xzFilterID - props uint32 - }{id: idLZMA2, props: props} - /* - * Process the filter list and create s.chain, going from last - * filter (LZMA2) to first filter - * - * First, LZMA2. - */ - ret = xzDecLZMA2Reset(s.lzma2, byte(filterList[filterTotal-1].props)) - if ret != xzOK { - return ret - } - s.chain = func(b *xzBuf) xzRet { - return xzDecLZMA2Run(s.lzma2, b) - } - /* - * Now the non-last filters - */ - for i := filterTotal - 2; i >= 0; i-- { - switch id := filterList[i].id; id { - case idDelta: - // delta filter - var delta *xzDecDelta - if s.deltasUsed < len(s.deltas) { - delta = s.deltas[s.deltasUsed] - } else { - delta = xzDecDeltaCreate() - s.deltas = append(s.deltas, delta) - } - s.deltasUsed++ - ret = xzDecDeltaReset(delta, int(filterList[i].props)+1) - if ret != xzOK { - return ret - } - chain := s.chain - s.chain = func(b *xzBuf) xzRet { - return xzDecDeltaRun(delta, b, chain) - } - case idBCJX86, idBCJPowerPC, idBCJIA64, - idBCJARM, idBCJARMThumb, idBCJSPARC: - // bcj filter - var bcj *xzDecBCJ - if s.bcjsUsed < len(s.bcjs) { - bcj = s.bcjs[s.bcjsUsed] - } else { - bcj = xzDecBCJCreate() - s.bcjs = append(s.bcjs, bcj) - } - s.bcjsUsed++ - ret = xzDecBCJReset(bcj, id, int(filterList[i].props)) - if ret != xzOK { - return ret - } - chain := s.chain - s.chain = func(b *xzBuf) xzRet { - return xzDecBCJRun(bcj, b, chain) - } - } - } - /* The rest must be Header Padding. */ - for s.temp.pos < len(s.temp.buf) { - if s.temp.buf[s.temp.pos] != 0x00 { - return xzOptionsError - } - s.temp.pos++ - } - s.temp.pos = 0 - s.block.compressed = 0 - s.block.uncompressed = 0 - return xzOK -} - -func decMain(s *xzDec, b *xzBuf) xzRet { - var ret xzRet - /* - * Store the start position for the case when we are in the middle - * of the Index field. - */ - s.inStart = b.inPos - for { - switch s.sequence { - case seqStreamHeader: - /* - * Stream Header is copied to s.temp, and then - * decoded from there. This way if the caller - * gives us only little input at a time, we can - * still keep the Stream Header decoding code - * simple. Similar approach is used in many places - * in this file. - */ - if !fillTemp(s, b) { - return xzOK - } - /* - * If decStreamHeader returns - * xzUnsupportedCheck, it is still possible - * to continue decoding. Thus, update s.sequence - * before calling decStreamHeader. - */ - s.sequence = seqBlockStart - ret = decStreamHeader(s) - if ret != xzOK { - return ret - } - fallthrough - case seqBlockStart: - /* We need one byte of input to continue. */ - if b.inPos == len(b.in) { - return xzOK - } - /* See if this is the beginning of the Index field. */ - if b.in[b.inPos] == 0 { - s.inStart = b.inPos - b.inPos++ - s.sequence = seqIndex - break - } - /* - * Calculate the size of the Block Header and - * prepare to decode it. - */ - s.blockHeader.size = (int(b.in[b.inPos]) + 1) * 4 - s.temp.buf = s.temp.bufArray[:s.blockHeader.size] - s.temp.pos = 0 - s.sequence = seqBlockHeader - fallthrough - case seqBlockHeader: - if !fillTemp(s, b) { - return xzOK - } - ret = decBlockHeader(s) - if ret != xzOK { - return ret - } - s.sequence = seqBlockUncompress - fallthrough - case seqBlockUncompress: - ret = decBlock(s, b) - if ret != xzStreamEnd { - return ret - } - s.sequence = seqBlockPadding - fallthrough - case seqBlockPadding: - /* - * Size of Compressed Data + Block Padding - * must be a multiple of four. We don't need - * s->block.compressed for anything else - * anymore, so we use it here to test the size - * of the Block Padding field. - */ - for s.block.compressed&3 != 0 { - if b.inPos == len(b.in) { - return xzOK - } - if b.in[b.inPos] != 0 { - return xzDataError - } - b.inPos++ - s.block.compressed++ - } - s.sequence = seqBlockCheck - fallthrough - case seqBlockCheck: - switch s.CheckType { - case CheckCRC32, CheckCRC64, CheckSHA256: - ret = checkValidate(s, b) - if ret != xzStreamEnd { - return ret - } - default: - if !checkSkip(s, b) { - return xzOK - } - } - s.sequence = seqBlockStart - case seqIndex: - ret = decIndex(s, b) - if ret != xzStreamEnd { - return ret - } - s.sequence = seqIndexPadding - fallthrough - case seqIndexPadding: - for (s.index.size+vliType(b.inPos-s.inStart))&3 != 0 { - if b.inPos == len(b.in) { - indexUpdate(s, b) - return xzOK - } - if b.in[b.inPos] != 0 { - return xzDataError - } - b.inPos++ - } - /* Finish the CRC32 value and Index size. */ - indexUpdate(s, b) - /* Compare the hashes to validate the Index field. */ - if !bytes.Equal( - s.block.hash.sha256.Sum(nil), s.index.hash.sha256.Sum(nil)) { - return xzDataError - } - s.sequence = seqIndexCRC32 - fallthrough - case seqIndexCRC32: - ret = crcValidate(s, b) - if ret != xzStreamEnd { - return ret - } - s.temp.buf = s.temp.bufArray[:streamHeaderSize] - s.sequence = seqStreamFooter - fallthrough - case seqStreamFooter: - if !fillTemp(s, b) { - return xzOK - } - return decStreamFooter(s) - } - } - /* Never reached */ -} - -/** - * xzDecRun - Run the XZ decoder - * @s: Decoder state allocated using xzDecInit - * @b: Input and output buffers - * - * See xzRet for details of return values. - * - * xzDecRun is a wrapper for decMain to handle some special cases. - * - * We must return xzBufError when it seems clear that we are not - * going to make any progress anymore. This is to prevent the caller - * from calling us infinitely when the input file is truncated or - * otherwise corrupt. Since zlib-style API allows that the caller - * fills the input buffer only when the decoder doesn't produce any - * new output, we have to be careful to avoid returning xzBufError - * too easily: xzBufError is returned only after the second - * consecutive call to xzDecRun that makes no progress. - */ -func xzDecRun(s *xzDec, b *xzBuf) xzRet { - inStart := b.inPos - outStart := b.outPos - ret := decMain(s, b) - if ret == xzOK && inStart == b.inPos && outStart == b.outPos { - if s.allowBufError { - ret = xzBufError - } - s.allowBufError = true - } else { - s.allowBufError = false - } - return ret -} - -/** - * xzDecInit - Allocate and initialize a XZ decoder state - * @dictMax: Maximum size of the LZMA2 dictionary (history buffer) for - * decoding. LZMA2 dictionary is always 2^n bytes - * or 2^n + 2^(n-1) bytes (the latter sizes are less common - * in practice), so other values for dictMax don't make sense. - * - * dictMax specifies the maximum allowed dictionary size that xzDecRun - * may allocate once it has parsed the dictionary size from the stream - * headers. This way excessive allocations can be avoided while still - * limiting the maximum memory usage to a sane value to prevent running the - * system out of memory when decompressing streams from untrusted sources. - * - * xzDecInit returns a pointer to an xzDec, which is ready to be used with - * xzDecRun. - */ -func xzDecInit(dictMax uint32, header *Header) *xzDec { - s := new(xzDec) - s.crc32 = crc32.NewIEEE() - s.Header = header - s.block.hash.sha256 = sha256.New() - s.index.hash.sha256 = sha256.New() - s.lzma2 = xzDecLZMA2Create(dictMax) - xzDecReset(s) - return s -} - -/** - * xzDecReset - Reset an already allocated decoder state - * @s: Decoder state allocated using xzDecInit - * - * This function can be used to reset the decoder state without - * reallocating memory with xzDecInit. - */ -func xzDecReset(s *xzDec) { - s.sequence = seqStreamHeader - s.allowBufError = false - s.pos = 0 - s.crc32.Reset() - s.check = nil - s.CheckType = checkUnset - s.block.compressed = 0 - s.block.uncompressed = 0 - s.block.count = 0 - s.block.hash.unpadded = 0 - s.block.hash.uncompressed = 0 - s.block.hash.sha256.Reset() - s.index.sequence = seqIndexCount - s.index.size = 0 - s.index.count = 0 - s.index.hash.unpadded = 0 - s.index.hash.uncompressed = 0 - s.index.hash.sha256.Reset() - s.temp.pos = 0 - s.temp.buf = s.temp.bufArray[:streamHeaderSize] - s.chain = nil - s.bcjsUsed = 0 - s.deltasUsed = 0 -} |