[Vm-dev] Integer overflow with BitBlt rule 20 and depth 32

Henrik Sperre Johansen henrik.s.johansen at veloxit.no
Wed Oct 21 07:06:40 UTC 2009


On 20.10.2009 15:56, David T. Lewis wrote:
>
> Could this be the cause of issue for which Juan was asking help?
>
>    Subject line "[Vm-dev] Bug in BitBlt. Need Help."
>    http://lists.squeakfoundation.org/pipermail/vm-dev/2009-September/003160.html
>    
Yes, that's exactly it, sorry I had not seen it.
Attached is a proof-of-concept fix (for partitionedAdd: only), valid as 
long as nParts > 1 ( I suggest one wouldn't use partitionedAdd anyways 
if it were :) )
If anyone has a better idea, it'd be appreciated!

Correctness test:
| sourceForm destForm blt correctAlphas |
     correctAlphas := 0.
     0  to: 255 do: [:sourceAlpha |
         sourceForm := Form extent: 1 @ 1 depth: 32.
         sourceForm bits at: 1 put: sourceAlpha << 24 + (33 << 16) + (25 
<< 8) + 27.
         0 to: 255 do: [:destAlpha |
             destForm := Form extent: 1 @ 1 depth: 32.
             destForm bits at: 1 put: destAlpha << 24 + (255 << 16) + 
(255 << 8) + 255.
              blt := BitBlt new.
              blt sourceForm: sourceForm.
              blt sourceOrigin: 0 @ 0.
              blt setDestForm: destForm.
              blt destOrigin: 0 @ 0.
              blt combinationRule: 20.
              blt copyBits.
              correctAlphas := correctAlphas
                + (((blt destForm bits at: 1) digitAt: 4) = (destAlpha + 
sourceAlpha min: 255)
                         ifTrue: [1]
                         ifFalse: [0])
      ]].
     self assert: 65536 equals: correctAlphas

Performance is not impacted to a significant degree as far as I can 
tell, the from runtimes of the test:
[|sourceForm destForm blt|
destForm := Form extent: 99 at 99 depth: 32.
1 to: destForm bits size do: [:ix |
destForm  bits at: ix put: ((192 << 24) + (255 << 16) + (255 << 8) + 255).].
sourceForm := Form extent: 99 at 99 depth: 32.
1 to: sourceForm bits size do: [:ix |
sourceForm bits at: ix put: ((192 << 24) + (33 << 16) + (25 << 8) + 27).].
blt := BitBlt new.
blt sourceForm: sourceForm.
blt sourceOrigin: 0 at 0.
blt setDestForm: destForm.
blt destOrigin: 0 at 0.
blt combinationRule: 20.
5000 timesRepeat: [
blt copyBits.]] timeToRun

Cheers,
Henry
-------------- next part --------------
'From Pharo1.1a of ''19 October 2009'' [Latest update: #11010] on 21 October 2009 at 2:13:43 am'!

!BitBltSimulation methodsFor: 'combination rules' stamp: 'HenrikSperreJohansen 10/21/2009 02:13'!
partitionedAdd: word1 to: word2 nBits: nBits nPartitions: nParts
	"Add word1 to word2 as nParts partitions of nBits each.
	This is useful for packed pixels, or packed colors"
	| mask sum result |
	mask := maskTable at: nBits.  "partition mask starts at the right"
	result := 0.
	1 to: nParts do:
		[:i |
		i = nParts ifFalse: [
		sum := (word1 bitAnd: mask) + (word2 bitAnd: mask).
		sum <= mask  "result must not carry out of partition"
			ifTrue: [result := result bitOr: sum]
			ifFalse: [result := result bitOr: mask].
		mask := mask << nBits  "slide left to next partition"] 
		"Avoid overflow when nBits*nParts = sizeOf: Integer"
			ifTrue: [|w1 w2|
		w1 := (word1 bitAnd: mask) >> nBits.
		w2 := (word2 bitAnd: mask) >> nBits.
		sum := w1 + w2.
		sum <= (mask >> nBits)  "result must not carry out of partition"
			ifTrue: [result := result bitOr: (sum <<nBits)]
			ifFalse: [result := result bitOr: mask].	
				
			]
	]
		.
	^ result
! !



More information about the Vm-dev mailing list