1
11
12 package xz
13
14 import (
15 "bytes"
16 "crypto/sha256"
17 "hash"
18 "hash/crc32"
19 "hash/crc64"
20 )
21
22
23
24
29 const (
30 streamHeaderSize = 12
31 headerMagic = "\xfd7zXZ\x00"
32 footerMagic = "YZ"
33 )
34
35
39 type vliType uint64
40
41 const (
42 vliUnknown vliType = ^vliType(0)
43
44 vliBytesMax = 8 * 8 / 7
45 )
46
47
48
49
50 type xzDecHash struct {
51 unpadded vliType
52 uncompressed vliType
53 sha256 hash.Hash
54 }
55
56
57 type xzDecSeq int
58
59 const (
60 seqStreamHeader xzDecSeq = iota
61 seqBlockStart
62 seqBlockHeader
63 seqBlockUncompress
64 seqBlockPadding
65 seqBlockCheck
66 seqIndex
67 seqIndexPadding
68 seqIndexCRC32
69 seqStreamFooter
70 )
71
72
73 type xzDecIndexSeq int
74
75 const (
76 seqIndexCount xzDecIndexSeq = iota
77 seqIndexUnpadded
78 seqIndexUncompressed
79 )
80
81
84 type xzDec struct {
85
86 sequence xzDecSeq
87
88 pos int
89
90 vli vliType
91
92 inStart int
93 outStart int
94
95 crc32 hash.Hash
96
97 checkCRC32 hash.Hash
98 checkCRC64 hash.Hash
99 checkSHA256 hash.Hash
100
101 check hash.Hash
102
103 *Header
104
108 allowBufError bool
109
110 blockHeader struct {
111
115 compressed vliType
116
120 uncompressed vliType
121
122 size int
123 }
124
125 block struct {
126
127 compressed vliType
128
129 uncompressed vliType
130
131 count vliType
132
136 hash xzDecHash
137 }
138
139 index struct {
140
141 sequence xzDecIndexSeq
142
143 size vliType
144
145 count vliType
146
150 hash xzDecHash
151 }
152
159 temp struct {
160 pos int
161 buf []byte
162 bufArray [1024]byte
163 }
164
165
166
167 chain func(b *xzBuf) xzRet
168
169 lzma2 *xzDecLZMA2
170
171 bcjs []*xzDecBCJ
172 deltas []*xzDecDelta
173
174 bcjsUsed int
175 deltasUsed int
176 }
177
178
179 var checkSizes = [...]byte{
180 0,
181 4, 4, 4,
182 8, 8, 8,
183 16, 16, 16,
184 32, 32, 32,
185 64, 64, 64,
186 }
187
188
194 func fillTemp(s *xzDec, b *xzBuf) bool {
195 copySize := len(b.in) - b.inPos
196 tempRemaining := len(s.temp.buf) - s.temp.pos
197 if copySize > tempRemaining {
198 copySize = tempRemaining
199 }
200 copy(s.temp.buf[s.temp.pos:], b.in[b.inPos:])
201 b.inPos += copySize
202 s.temp.pos += copySize
203 if s.temp.pos == len(s.temp.buf) {
204 s.temp.pos = 0
205 return true
206 }
207 return false
208 }
209
210
211 func decVLI(s *xzDec, in []byte, inPos *int) xzRet {
212 var byte byte
213 if s.pos == 0 {
214 s.vli = 0
215 }
216 for *inPos < len(in) {
217 byte = in[*inPos]
218 *inPos++
219 s.vli |= vliType(byte&0x7f) << uint(s.pos)
220 if byte&0x80 == 0 {
221
222 if byte == 0 && s.pos != 0 {
223 return xzDataError
224 }
225 s.pos = 0
226 return xzStreamEnd
227 }
228 s.pos += 7
229 if s.pos == 7*vliBytesMax {
230 return xzDataError
231 }
232 }
233 return xzOK
234 }
235
236
248 func decBlock(s *xzDec, b *xzBuf) xzRet {
249 var ret xzRet
250 s.inStart = b.inPos
251 s.outStart = b.outPos
252 ret = s.chain(b)
253 s.block.compressed += vliType(b.inPos - s.inStart)
254 s.block.uncompressed += vliType(b.outPos - s.outStart)
255
259 if s.block.compressed > s.blockHeader.compressed ||
260 s.block.uncompressed > s.blockHeader.uncompressed {
261 return xzDataError
262 }
263 switch s.CheckType {
264 case CheckCRC32, CheckCRC64, CheckSHA256:
265 _, _ = s.check.Write(b.out[s.outStart:b.outPos])
266 }
267 if ret == xzStreamEnd {
268 if s.blockHeader.compressed != vliUnknown &&
269 s.blockHeader.compressed != s.block.compressed {
270 return xzDataError
271 }
272 if s.blockHeader.uncompressed != vliUnknown &&
273 s.blockHeader.uncompressed != s.block.uncompressed {
274 return xzDataError
275 }
276 s.block.hash.unpadded +=
277 vliType(s.blockHeader.size) + s.block.compressed
278 s.block.hash.unpadded += vliType(checkSizes[s.CheckType])
279 s.block.hash.uncompressed += s.block.uncompressed
280 var buf [2 * 8]byte
281 putLE64(uint64(s.block.hash.unpadded), buf[:])
282 putLE64(uint64(s.block.hash.uncompressed), buf[8:])
283 _, _ = s.block.hash.sha256.Write(buf[:])
284 s.block.count++
285 }
286 return ret
287 }
288
289
290 func indexUpdate(s *xzDec, b *xzBuf) {
291 inUsed := b.inPos - s.inStart
292 s.index.size += vliType(inUsed)
293 _, _ = s.crc32.Write(b.in[s.inStart : s.inStart+inUsed])
294 }
295
296
304 func decIndex(s *xzDec, b *xzBuf) xzRet {
305 var ret xzRet
306 for {
307 ret = decVLI(s, b.in, &b.inPos)
308 if ret != xzStreamEnd {
309 indexUpdate(s, b)
310 return ret
311 }
312 switch s.index.sequence {
313 case seqIndexCount:
314 s.index.count = s.vli
315
320 if s.index.count != s.block.count {
321 return xzDataError
322 }
323 s.index.sequence = seqIndexUnpadded
324 case seqIndexUnpadded:
325 s.index.hash.unpadded += s.vli
326 s.index.sequence = seqIndexUncompressed
327 case seqIndexUncompressed:
328 s.index.hash.uncompressed += s.vli
329 var buf [2 * 8]byte
330 putLE64(uint64(s.index.hash.unpadded), buf[:])
331 putLE64(uint64(s.index.hash.uncompressed), buf[8:])
332 _, _ = s.index.hash.sha256.Write(buf[:])
333 s.index.count--
334 s.index.sequence = seqIndexUnpadded
335 }
336 if !(s.index.count > 0) {
337 break
338 }
339 }
340 return xzStreamEnd
341 }
342
343
347 func crcValidate(s *xzDec, b *xzBuf) xzRet {
348 sum := s.crc32.Sum(nil)
349
350 sum[0], sum[1], sum[2], sum[3] = sum[3], sum[2], sum[1], sum[0]
351 for {
352 if b.inPos == len(b.in) {
353 return xzOK
354 }
355 if sum[s.pos] != b.in[b.inPos] {
356 return xzDataError
357 }
358 b.inPos++
359 s.pos++
360 if !(s.pos < 4) {
361 break
362 }
363 }
364 s.crc32.Reset()
365 s.pos = 0
366 return xzStreamEnd
367 }
368
369
373 func checkValidate(s *xzDec, b *xzBuf) xzRet {
374 sum := s.check.Sum(nil)
375 if s.CheckType == CheckCRC32 || s.CheckType == CheckCRC64 {
376
377 for i, j := 0, len(sum)-1; i < j; i, j = i+1, j-1 {
378 sum[i], sum[j] = sum[j], sum[i]
379 }
380 }
381 for {
382 if b.inPos == len(b.in) {
383 return xzOK
384 }
385 if sum[s.pos] != b.in[b.inPos] {
386 return xzDataError
387 }
388 b.inPos++
389 s.pos++
390 if !(s.pos < len(sum)) {
391 break
392 }
393 }
394 s.check.Reset()
395 s.pos = 0
396 return xzStreamEnd
397 }
398
399
403 func checkSkip(s *xzDec, b *xzBuf) bool {
404 for s.pos < int(checkSizes[s.CheckType]) {
405 if b.inPos == len(b.in) {
406 return false
407 }
408 b.inPos++
409 s.pos++
410 }
411 s.pos = 0
412 return true
413 }
414
415
416 var xzCRC64Table = crc64.MakeTable(crc64.ECMA)
417
418
419 func decStreamHeader(s *xzDec) xzRet {
420 if string(s.temp.buf[:len(headerMagic)]) != headerMagic {
421 return xzFormatError
422 }
423 if crc32.ChecksumIEEE(s.temp.buf[len(headerMagic):len(headerMagic)+2]) !=
424 getLE32(s.temp.buf[len(headerMagic)+2:]) {
425 return xzDataError
426 }
427 if s.temp.buf[len(headerMagic)] != 0 {
428 return xzOptionsError
429 }
430
436 s.CheckType = CheckID(s.temp.buf[len(headerMagic)+1])
437 if s.CheckType > checkMax {
438 return xzOptionsError
439 }
440 switch s.CheckType {
441 case CheckNone:
442
443 case CheckCRC32:
444 if s.checkCRC32 == nil {
445 s.checkCRC32 = crc32.NewIEEE()
446 } else {
447 s.checkCRC32.Reset()
448 }
449 s.check = s.checkCRC32
450 case CheckCRC64:
451 if s.checkCRC64 == nil {
452 s.checkCRC64 = crc64.New(xzCRC64Table)
453 } else {
454 s.checkCRC64.Reset()
455 }
456 s.check = s.checkCRC64
457 case CheckSHA256:
458 if s.checkSHA256 == nil {
459 s.checkSHA256 = sha256.New()
460 } else {
461 s.checkSHA256.Reset()
462 }
463 s.check = s.checkSHA256
464 default:
465 return xzUnsupportedCheck
466 }
467 return xzOK
468 }
469
470
471 func decStreamFooter(s *xzDec) xzRet {
472 if string(s.temp.buf[10:10+len(footerMagic)]) != footerMagic {
473 return xzDataError
474 }
475 if crc32.ChecksumIEEE(s.temp.buf[4:10]) != getLE32(s.temp.buf) {
476 return xzDataError
477 }
478
483 if s.index.size>>2 != vliType(getLE32(s.temp.buf[4:])) {
484 return xzDataError
485 }
486 if s.temp.buf[8] != 0 || CheckID(s.temp.buf[9]) != s.CheckType {
487 return xzDataError
488 }
489
493 return xzStreamEnd
494 }
495
496
497 func decBlockHeader(s *xzDec) xzRet {
498 var ret xzRet
499
503 crc := getLE32(s.temp.buf[len(s.temp.buf)-4:])
504 s.temp.buf = s.temp.buf[:len(s.temp.buf)-4]
505 if crc32.ChecksumIEEE(s.temp.buf) != crc {
506 return xzDataError
507 }
508 s.temp.pos = 2
509
512 if s.temp.buf[1]&0x3C != 0 {
513 return xzOptionsError
514 }
515
516 if s.temp.buf[1]&0x40 != 0 {
517 if decVLI(s, s.temp.buf, &s.temp.pos) != xzStreamEnd {
518 return xzDataError
519 }
520 if s.vli >= 1<<63-8 {
521
522
523 return xzDataError
524 }
525 if s.vli == 0 {
526
527 return xzDataError
528 }
529 s.blockHeader.compressed = s.vli
530 } else {
531 s.blockHeader.compressed = vliUnknown
532 }
533
534 if s.temp.buf[1]&0x80 != 0 {
535 if decVLI(s, s.temp.buf, &s.temp.pos) != xzStreamEnd {
536 return xzDataError
537 }
538 s.blockHeader.uncompressed = s.vli
539 } else {
540 s.blockHeader.uncompressed = vliUnknown
541 }
542
543 filterTotal := int(s.temp.buf[1]&0x03) + 1
544
545 filterList := make([]struct {
546 id xzFilterID
547 props uint32
548 }, filterTotal)
549
550 for i := 0; i < filterTotal-1; i++ {
551
552 if len(s.temp.buf)-s.temp.pos < 2 {
553 return xzDataError
554 }
555 s.temp.pos += 2
556 switch id := xzFilterID(s.temp.buf[s.temp.pos-2]); id {
557 case idDelta:
558
559 if s.temp.buf[s.temp.pos-1] != 0x01 {
560 return xzOptionsError
561 }
562
563 if len(s.temp.buf)-s.temp.pos < 1 {
564 return xzDataError
565 }
566 props := uint32(s.temp.buf[s.temp.pos])
567 s.temp.pos++
568 filterList[i] = struct {
569 id xzFilterID
570 props uint32
571 }{id: id, props: props}
572 case idBCJX86, idBCJPowerPC, idBCJIA64,
573 idBCJARM, idBCJARMThumb, idBCJSPARC:
574
575 var props uint32
576 switch s.temp.buf[s.temp.pos-1] {
577 case 0x00:
578 props = 0
579 case 0x04:
580 if len(s.temp.buf)-s.temp.pos < 4 {
581 return xzDataError
582 }
583 props = getLE32(s.temp.buf[s.temp.pos:])
584 s.temp.pos += 4
585 default:
586 return xzOptionsError
587 }
588 filterList[i] = struct {
589 id xzFilterID
590 props uint32
591 }{id: id, props: props}
592 default:
593 return xzOptionsError
594 }
595 }
596
599 if len(s.temp.buf)-s.temp.pos < 2 {
600 return xzDataError
601 }
602
603 if xzFilterID(s.temp.buf[s.temp.pos]) != idLZMA2 {
604 return xzOptionsError
605 }
606 s.temp.pos++
607
608 if s.temp.buf[s.temp.pos] != 0x01 {
609 return xzOptionsError
610 }
611 s.temp.pos++
612
613 if len(s.temp.buf)-s.temp.pos < 1 {
614 return xzDataError
615 }
616 props := uint32(s.temp.buf[s.temp.pos])
617 s.temp.pos++
618 filterList[filterTotal-1] = struct {
619 id xzFilterID
620 props uint32
621 }{id: idLZMA2, props: props}
622
628 ret = xzDecLZMA2Reset(s.lzma2, byte(filterList[filterTotal-1].props))
629 if ret != xzOK {
630 return ret
631 }
632 s.chain = func(b *xzBuf) xzRet {
633 return xzDecLZMA2Run(s.lzma2, b)
634 }
635
638 for i := filterTotal - 2; i >= 0; i-- {
639 switch id := filterList[i].id; id {
640 case idDelta:
641
642 var delta *xzDecDelta
643 if s.deltasUsed < len(s.deltas) {
644 delta = s.deltas[s.deltasUsed]
645 } else {
646 delta = xzDecDeltaCreate()
647 s.deltas = append(s.deltas, delta)
648 }
649 s.deltasUsed++
650 ret = xzDecDeltaReset(delta, int(filterList[i].props)+1)
651 if ret != xzOK {
652 return ret
653 }
654 chain := s.chain
655 s.chain = func(b *xzBuf) xzRet {
656 return xzDecDeltaRun(delta, b, chain)
657 }
658 case idBCJX86, idBCJPowerPC, idBCJIA64,
659 idBCJARM, idBCJARMThumb, idBCJSPARC:
660
661 var bcj *xzDecBCJ
662 if s.bcjsUsed < len(s.bcjs) {
663 bcj = s.bcjs[s.bcjsUsed]
664 } else {
665 bcj = xzDecBCJCreate()
666 s.bcjs = append(s.bcjs, bcj)
667 }
668 s.bcjsUsed++
669 ret = xzDecBCJReset(bcj, id, int(filterList[i].props))
670 if ret != xzOK {
671 return ret
672 }
673 chain := s.chain
674 s.chain = func(b *xzBuf) xzRet {
675 return xzDecBCJRun(bcj, b, chain)
676 }
677 }
678 }
679
680 for s.temp.pos < len(s.temp.buf) {
681 if s.temp.buf[s.temp.pos] != 0x00 {
682 return xzOptionsError
683 }
684 s.temp.pos++
685 }
686 s.temp.pos = 0
687 s.block.compressed = 0
688 s.block.uncompressed = 0
689 return xzOK
690 }
691
692 func decMain(s *xzDec, b *xzBuf) xzRet {
693 var ret xzRet
694
698 s.inStart = b.inPos
699 for {
700 switch s.sequence {
701 case seqStreamHeader:
702
710 if !fillTemp(s, b) {
711 return xzOK
712 }
713
719 s.sequence = seqBlockStart
720 ret = decStreamHeader(s)
721 if ret != xzOK {
722 return ret
723 }
724 fallthrough
725 case seqBlockStart:
726
727 if b.inPos == len(b.in) {
728 return xzOK
729 }
730
731 if b.in[b.inPos] == 0 {
732 s.inStart = b.inPos
733 b.inPos++
734 s.sequence = seqIndex
735 break
736 }
737
741 s.blockHeader.size = (int(b.in[b.inPos]) + 1) * 4
742 s.temp.buf = s.temp.bufArray[:s.blockHeader.size]
743 s.temp.pos = 0
744 s.sequence = seqBlockHeader
745 fallthrough
746 case seqBlockHeader:
747 if !fillTemp(s, b) {
748 return xzOK
749 }
750 ret = decBlockHeader(s)
751 if ret != xzOK {
752 return ret
753 }
754 s.sequence = seqBlockUncompress
755 fallthrough
756 case seqBlockUncompress:
757 ret = decBlock(s, b)
758 if ret != xzStreamEnd {
759 return ret
760 }
761 s.sequence = seqBlockPadding
762 fallthrough
763 case seqBlockPadding:
764
771 for s.block.compressed&3 != 0 {
772 if b.inPos == len(b.in) {
773 return xzOK
774 }
775 if b.in[b.inPos] != 0 {
776 return xzDataError
777 }
778 b.inPos++
779 s.block.compressed++
780 }
781 s.sequence = seqBlockCheck
782 fallthrough
783 case seqBlockCheck:
784 switch s.CheckType {
785 case CheckCRC32, CheckCRC64, CheckSHA256:
786 ret = checkValidate(s, b)
787 if ret != xzStreamEnd {
788 return ret
789 }
790 default:
791 if !checkSkip(s, b) {
792 return xzOK
793 }
794 }
795 s.sequence = seqBlockStart
796 case seqIndex:
797 ret = decIndex(s, b)
798 if ret != xzStreamEnd {
799 return ret
800 }
801 s.sequence = seqIndexPadding
802 fallthrough
803 case seqIndexPadding:
804 for (s.index.size+vliType(b.inPos-s.inStart))&3 != 0 {
805 if b.inPos == len(b.in) {
806 indexUpdate(s, b)
807 return xzOK
808 }
809 if b.in[b.inPos] != 0 {
810 return xzDataError
811 }
812 b.inPos++
813 }
814
815 indexUpdate(s, b)
816
817 if !bytes.Equal(
818 s.block.hash.sha256.Sum(nil), s.index.hash.sha256.Sum(nil)) {
819 return xzDataError
820 }
821 s.sequence = seqIndexCRC32
822 fallthrough
823 case seqIndexCRC32:
824 ret = crcValidate(s, b)
825 if ret != xzStreamEnd {
826 return ret
827 }
828 s.temp.buf = s.temp.bufArray[:streamHeaderSize]
829 s.sequence = seqStreamFooter
830 fallthrough
831 case seqStreamFooter:
832 if !fillTemp(s, b) {
833 return xzOK
834 }
835 return decStreamFooter(s)
836 }
837 }
838
839 }
840
841
859 func xzDecRun(s *xzDec, b *xzBuf) xzRet {
860 inStart := b.inPos
861 outStart := b.outPos
862 ret := decMain(s, b)
863 if ret == xzOK && inStart == b.inPos && outStart == b.outPos {
864 if s.allowBufError {
865 ret = xzBufError
866 }
867 s.allowBufError = true
868 } else {
869 s.allowBufError = false
870 }
871 return ret
872 }
873
874
890 func xzDecInit(dictMax uint32, header *Header) *xzDec {
891 s := new(xzDec)
892 s.crc32 = crc32.NewIEEE()
893 s.Header = header
894 s.block.hash.sha256 = sha256.New()
895 s.index.hash.sha256 = sha256.New()
896 s.lzma2 = xzDecLZMA2Create(dictMax)
897 xzDecReset(s)
898 return s
899 }
900
901
908 func xzDecReset(s *xzDec) {
909 s.sequence = seqStreamHeader
910 s.allowBufError = false
911 s.pos = 0
912 s.crc32.Reset()
913 s.check = nil
914 s.CheckType = checkUnset
915 s.block.compressed = 0
916 s.block.uncompressed = 0
917 s.block.count = 0
918 s.block.hash.unpadded = 0
919 s.block.hash.uncompressed = 0
920 s.block.hash.sha256.Reset()
921 s.index.sequence = seqIndexCount
922 s.index.size = 0
923 s.index.count = 0
924 s.index.hash.unpadded = 0
925 s.index.hash.uncompressed = 0
926 s.index.hash.sha256.Reset()
927 s.temp.pos = 0
928 s.temp.buf = s.temp.bufArray[:streamHeaderSize]
929 s.chain = nil
930 s.bcjsUsed = 0
931 s.deltasUsed = 0
932 }
933
View as plain text