[squeak-dev] The Trunk: Compression-eem.41.mcz

commits at source.squeak.org commits at source.squeak.org
Tue May 6 22:03:20 UTC 2014


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.
  		].
  	].!



More information about the Squeak-dev mailing list