Bugs in ByteArray>>dwordAtOffset:put: and basicDwordAtOffset:put:

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Bugs in ByteArray>>dwordAtOffset:put: and basicDwordAtOffset:put:

Carsten Haerle
The following code works as expected:

a := #[0 0 0 0].
a dwordAtOffset: 0 put: 16rFFFFFFFF.
a

the following code raises an Exception "Can't a DWORD"

a := #[0 0 0 0].
a dwordAtOffset: 0 put: (DWORD fromInteger: 16rFFFFFFFF).
a


The exception occurs in the method ByteArray>>retryDwordAtOffset:put: which
seems to have an off by one error. In Addition the implementation comment
seems to be totally wrong. Below a fixed version:


!ByteArray methodsFor!

retryDwordAtOffset: anInteger put: anObject
 "Private - Fallback code for storing unsigned word into the reciever when a
primitive fails.
 Either raises an appropriate error, or converts the argument to an Integer
and retries."

 (self validateOffset: anInteger) == 2
  ifTrue:
   ["Not a suitable value - could be non-Numeric, or not in unsigned 32-bit
range.
   Attempt to coerce to Integer and retry. anObject may not understand
asInteger."

   | intVal |
   intVal := anObject asInteger.
   (intVal >= 0 and: [intVal <= 4294967295])
    ifTrue: [^self dwordAtOffset: anInteger put: intVal]].
 ^self errorCantHold: anObject! !
!ByteArray categoriesFor: #retryDwordAtOffset:put:!accessing!private! !


In addition almost the same code has been copied to
ByteArray>>basicDwordAtOffset:put: (which already has a corrected comment
but still the wrong code). I thing it should also use the method
#retryDwordAtOffset:put: as shown below.

Why are there two method anyway?


!ByteArray methodsFor!

basicDwordAtOffset: anInteger put: anObject
 "Private - Replace the internal contents of the receiver from offset
anInteger with
 the first 4 bytes of anObject."

 <primitive: 121>
^self retryDwordAtOffset: anInteger put: anObject! !
!ByteArray categoriesFor:
#basicDwordAtOffset:put:!accessing!primitives!private! !


Regards

Carsten


Reply | Threaded
Open this post in threaded view
|

Re: Bugs in ByteArray>>dwordAtOffset:put: and basicDwordAtOffset:put:

Blair McGlashan
"Carsten Haerle" <[hidden email]> wrote in message
news:brkk9h$8vs$03$[hidden email]...
> ..
> the following code raises an Exception "Can't a DWORD"
>
> a := #[0 0 0 0].
> a dwordAtOffset: 0 put: (DWORD fromInteger: 16rFFFFFFFF).
> ...
> The exception occurs in the method ByteArray>>retryDwordAtOffset:put:
which
> seems to have an off by one error. In Addition the implementation comment
> seems to be totally wrong. Below a fixed version:
> ...

Thanks Carsten. Recorded as bug #1457.

>
> In addition almost the same code has been copied to
> ByteArray>>basicDwordAtOffset:put: (which already has a corrected comment
> but still the wrong code). I thing it should also use the method
> #retryDwordAtOffset:put: as shown below.
>
> Why are there two method anyway?
>

This is so that the ExternalAddress subclass can discriminate between
setting the address (i.e. setting up the pointer), or writing at some offset
from the address (i.e. using it as a pointer). The basic version can't use
#retryDwordAtOffset:put: because that would then give incorrect behaviour
for subclasses.

I'll correct the relational test on the upper bound in
#basicDwordAtOffset:put: under the same defect number, and do the same for
#retryWordAtOffset:put: which suffers from the same error too.

Regards

Blair