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

David T. Lewis lewis at mail.msen.com
Sun Nov 1 18:58:10 UTC 2009


On Fri, Oct 30, 2009 at 10:14:52AM -0300, Juan Vuletich wrote:
> 
> David T. Lewis wrote:
> >
> >Juan's patches (VMMaker-BitBlt-AlphaFixes-jmv-M7407.cs on Mantis 7047)
> >do resolve the problems in the VM, and the changes all look correct to me
> >(but I have no experience with bitblt, so I'm just commenting on the fixes
> >for type declarations and arithmetic overflow). 
> >
> >Has anyone else had a chance to review this? If there are no issues or
> >concerns, I will add Juan's alpha fixes to VMMaker.
> >
> >Dave
> 
> 
> Good. Thanks!

Hi Juan,

There are a couple of spelling error in comments in your alpha
patches for bitblt. I corrected them by editing the change set
as follows:

  #!/bin/sh
  sed 's/aritm/arithm/g' VMMaker-BitBlt-AlphaFixes-jmv-M7407.cs \
    | sed 's/operarions/operations/g' \
    > VMMaker-BitBlt-AlphaFixes-jmv-M7407-patched.cs

May I have your permission to use the edited version in VMMaker?
This preserves your author initials and time stamps but corrects
the minor spelling errors.

This may sound like a silly request, but I did not want to modify
any methods with your initials without asking you first.

Thanks,
Dave

-------------- next part --------------
'From Squeak3.10.2 of ''5 June 2008'' [latest update: #7179] on 26 October 2009 at 9:25:13 am'!

!BitBltSimulation methodsFor: 'combination rules' stamp: 'jmv 10/26/2009 08:58'!
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 maskedWord1 |
	"In C, most arithmethic operations answer the same bit pattern regardless of the operands being signed or unsigned ints
	(this is due to the way 2's complement numbers work). However, comparisions might fail. Add the proper declaration of
	words as unsigned int in those cases where comparisions are done (jmv)"
	self var: #word1 type: 'unsigned int'.
	self var: #word2 type: 'unsigned int'.
	self var: #mask type: 'unsigned int'.
	self var: #sum type: 'unsigned int'.
	self var: #result type: 'unsigned int'.
	self var: #maskedWord1 type: 'unsigned int'.
	mask := maskTable at: nBits.  "partition mask starts at the right"
	result := 0.
	1 to: nParts do:
		[:i |
		maskedWord1 := word1 bitAnd: mask.
		sum := maskedWord1 + (word2 bitAnd: mask).
		(sum <= mask "result must not carry out of partition"
				and: [ sum >= maskedWord1 ])	"This is needed because in C, integer arithmethic overflows silently!! (jmv)"
			ifTrue: [result := result bitOr: sum]
			ifFalse: [result := result bitOr: mask].
		mask := mask << nBits  "slide left to next partition"].
	^ result
! !

!BitBltSimulation methodsFor: 'combination rules' stamp: 'jmv 10/26/2009 08:59'!
partitionedMax: word1 with: word2 nBits: nBits nPartitions: nParts
	"Max word1 to word2 as nParts partitions of nBits each"
	| mask result |
	"In C, most arithmethic operations answer the same bit pattern regardless of the operands being signed or unsigned ints
	(this is due to the way 2's complement numbers work). However, comparisions might fail. Add the proper declaration of
	words as unsigned int in those cases where comparisions are done (jmv)"
	self var: #word1 type: 'unsigned int'.
	self var: #word2 type: 'unsigned int'.
	self var: #mask type: 'unsigned int'.
	self var: #result type: 'unsigned int'.
	mask := maskTable at: nBits.  "partition mask starts at the right"
	result := 0.
	1 to: nParts do:
		[:i |
		result := result bitOr: ((word2 bitAnd: mask) max: (word1 bitAnd: mask)).
		mask := mask << nBits  "slide left to next partition"].
	^ result
! !

!BitBltSimulation methodsFor: 'combination rules' stamp: 'jmv 10/26/2009 08:59'!
partitionedMin: word1 with: word2 nBits: nBits nPartitions: nParts
	"Min word1 to word2 as nParts partitions of nBits each"
	| mask result |
	"In C, most arithmethic operations answer the same bit pattern regardless of the operands being signed or unsigned ints
	(this is due to the way 2's complement numbers work). However, comparisions might fail. Add the proper declaration of
	words as unsigned int in those cases where comparisions are done (jmv)"
	self var: #word1 type: 'unsigned int'.
	self var: #word2 type: 'unsigned int'.
	self var: #mask type: 'unsigned int'.
	self var: #result type: 'unsigned int'.
	mask := maskTable at: nBits.  "partition mask starts at the right"
	result := 0.
	1 to: nParts do:
		[:i |
		result := result bitOr: ((word2 bitAnd: mask) min: (word1 bitAnd: mask)).
		mask := mask << nBits  "slide left to next partition"].
	^ result
! !

!BitBltSimulation methodsFor: 'combination rules' stamp: 'jmv 10/26/2009 09:01'!
partitionedMul: word1 with: word2 nBits: nBits nPartitions: nParts
	"Multiply word1 with word2 as nParts partitions of nBits each.
	This is useful for packed pixels, or packed colors.
	Bug in loop version when non-white background"

	| sMask product result dMask |
	"In C, integer multiplication might answer a wrong value if the unsigned values are declared as signed.
	This problem does not affect this method, because the most significant bit (i.e. the sign bit) will
	always be zero (jmv)"
	sMask := maskTable at: nBits.  "partition mask starts at the right"
	dMask :=  sMask << nBits.
	result := (((word1 bitAnd: sMask)+1) * ((word2 bitAnd: sMask)+1) - 1 
				bitAnd: dMask) >> nBits.	"optimized first step"
	nParts = 1
		ifTrue: [ ^result ].
	product := (((word1>>nBits bitAnd: sMask)+1) * ((word2>>nBits bitAnd: sMask)+1) - 1 bitAnd: dMask).
	result := result bitOr: product.
	nParts = 2
		ifTrue: [ ^result ].
	product := (((word1>>(2*nBits) bitAnd: sMask)+1) * ((word2>>(2*nBits) bitAnd: sMask)+1) - 1 bitAnd: dMask).
	result := result bitOr: product << nBits.
	nParts = 3
		ifTrue: [ ^result ].
	product := (((word1>>(3*nBits) bitAnd: sMask)+1) * ((word2>>(3*nBits) bitAnd: sMask)+1) - 1 bitAnd: dMask).
	result := result bitOr: product << (2*nBits).
	^ result

"	| sMask product result dMask |
	sMask := maskTable at: nBits.  'partition mask starts at the right'
	dMask :=  sMask << nBits.
	result := (((word1 bitAnd: sMask)+1) * ((word2 bitAnd: sMask)+1) - 1 
				bitAnd: dMask) >> nBits.	'optimized first step'
	nBits to: nBits * (nParts-1) by: nBits do: [:ofs |
		product := (((word1>>ofs bitAnd: sMask)+1) * ((word2>>ofs bitAnd: sMask)+1) - 1 bitAnd: dMask).
		result := result bitOr: (product bitAnd: dMask) << (ofs-nBits)].
	^ result"! !

!BitBltSimulation methodsFor: 'combination rules' stamp: 'jmv 10/26/2009 08:59'!
partitionedSub: word1 from: word2 nBits: nBits nPartitions: nParts
	"Subtract word1 from word2 as nParts partitions of nBits each.
	This is useful for packed pixels, or packed colors"
	| mask result p1 p2 |
	"In C, most arithmethic operations answer the same bit pattern regardless of the operands being signed or unsigned ints
	(this is due to the way 2's complement numbers work). However, comparisions might fail. Add the proper declaration of
	words as unsigned int in those cases where comparisions are done (jmv)"
	self var: #word1 type: 'unsigned int'.
	self var: #word2 type: 'unsigned int'.
	self var: #p1 type: 'unsigned int'.
	self var: #p2 type: 'unsigned int'.
	self var: #mask type: 'unsigned int'.
	self var: #result type: 'unsigned int'.
	mask := maskTable at: nBits.  "partition mask starts at the right"
	result := 0.
	1 to: nParts do:
		[:i |
		p1 := word1 bitAnd: mask.
		p2 := word2 bitAnd: mask.
		p1 < p2  "result is really abs value of thedifference"
			ifTrue: [result := result bitOr: p2 - p1]
			ifFalse: [result := result bitOr: p1 - p2].
		mask := mask << nBits  "slide left to next partition"].
	^ result
! !



More information about the Vm-dev mailing list