[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