Eliot Miranda uploaded a new version of Compression to project The Trunk:
http://source.squeak.org/trunk/Compression-eem.41.mcz ==================== Summary ==================== Name: Compression-eem.41 Author: eem Time: 6 May 2014, 3:03:07.032 pm UUID: 331a0bb5-cbf5-4a72-9b2b-f4a5ab92e6c2 Ancestors: Compression-fbs.40 Fix a bug in [Fast]InflateStream, thanks to Yoshiki Oshima: This can be a nitpick of the year, but there is a bug in InflateStream>>decompressBlock:with: There is a part that reads (toward the end): ------------------------ collection replaceFrom: readLimit+1 to: readLimit + length + 1 with: collection startingAt: readLimit - distance + 1. ------------------------ but here we want to replace "length" bytes in collection, as opposed to length + 1 bytes, so it has to say: ------------------------ collection replaceFrom: readLimit+1 to: readLimit + length with: collection startingAt: readLimit - distance + 1. ------------------------ (So is the non-primitive version in FastInflateStream.) The reason it does not matter is that replaceFrom:to:with:startingAt: does not care about the source and destination being the same and overlap between them. Even when the above bug puts one extra bytes in collection temporarily, the extra byte will be wiped out in the next iteration of the loop surrounding it. However, if you try to port this to a language that does the "right thing" when there is an overlap, it manifests as a bug. -- Yoshiki P.S. It was a "rare" delight to point out a bug in Andreas' code^^; We miss you. =============== Diff against Compression-fbs.40 =============== Item was changed: ----- Method: FastInflateStream>>decompressBlock:with: (in category 'inflating') ----- decompressBlock: llTable with: dTable "Process the compressed data in the block. llTable is the huffman table for literal/length codes and dTable is the huffman table for distance codes." | value extra length distance oldPos oldBits oldBitPos | <primitive: 'primitiveInflateDecompressBlock' module: 'ZipPlugin'> [readLimit < collection size and:[sourcePos <= sourceLimit]] whileTrue:[ "Back up stuff if we're running out of space" oldBits := bitBuf. oldBitPos := bitPos. oldPos := sourcePos. value := self decodeValueFrom: llTable. value < 256 ifTrue:[ "A literal" collection byteAt: (readLimit := readLimit + 1) put: value. ] ifFalse:["length/distance or end of block" value = 256 ifTrue:["End of block" state := state bitAnd: StateNoMoreData. ^self]. "Compute the actual length value (including possible extra bits)" extra := (value bitShift: -16) - 1. length := value bitAnd: 16rFFFF. extra > 0 ifTrue:[length := length + (self nextBits: extra)]. "Compute the distance value" value := self decodeValueFrom: dTable. extra := (value bitShift: -16). distance := value bitAnd: 16rFFFF. extra > 0 ifTrue:[distance := distance + (self nextBits: extra)]. (readLimit + length >= collection size) ifTrue:[ bitBuf := oldBits. bitPos := oldBitPos. sourcePos := oldPos. ^self]. collection replaceFrom: readLimit+1 + to: readLimit + length - to: readLimit + length + 1 with: collection startingAt: readLimit - distance + 1. readLimit := readLimit + length. ]. ].! Item was changed: ----- Method: InflateStream>>decompressBlock:with: (in category 'inflating') ----- decompressBlock: llTable with: dTable "Process the compressed data in the block. llTable is the huffman table for literal/length codes and dTable is the huffman table for distance codes." | value extra length distance oldPos oldBits oldBitPos | [readLimit < collection size and:[sourcePos <= sourceLimit]] whileTrue:[ "Back up stuff if we're running out of space" oldBits := bitBuf. oldBitPos := bitPos. oldPos := sourcePos. value := self decodeValueFrom: llTable. value < 256 ifTrue:[ "A literal" collection byteAt: (readLimit := readLimit + 1) put: value. ] ifFalse:["length/distance or end of block" value = 256 ifTrue:["End of block" state := state bitAnd: StateNoMoreData. ^self]. "Compute the actual length value (including possible extra bits)" extra := #(0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 0) at: value - 256. length := #(3 4 5 6 7 8 9 10 11 13 15 17 19 23 27 31 35 43 51 59 67 83 99 115 131 163 195 227 258) at: value - 256. extra > 0 ifTrue:[length := length + (self nextBits: extra)]. "Compute the distance value" value := self decodeValueFrom: dTable. extra := #(0 0 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13) at: value+1. distance := #(1 2 3 4 5 7 9 13 17 25 33 49 65 97 129 193 257 385 513 769 1025 1537 2049 3073 4097 6145 8193 12289 16385 24577) at: value+1. extra > 0 ifTrue:[distance := distance + (self nextBits: extra)]. (readLimit + length >= collection size) ifTrue:[ bitBuf := oldBits. bitPos := oldBitPos. sourcePos := oldPos. ^self]. collection replaceFrom: readLimit+1 + to: readLimit + length - to: readLimit + length + 1 with: collection startingAt: readLimit - distance + 1. readLimit := readLimit + length. ]. ].! |
Free forum by Nabble | Edit this page |