[Vm-dev] VM Maker: VMMaker.oscog-eem.2338.mcz

Levente Uzonyi leves at caesar.elte.hu
Mon Feb 26 00:12:20 UTC 2018


Hi Eliot,

I went through the primitives and found the following issues:

primitiveCompareString
- size of the order variable should be checked to be 256 as it is done in primitiveFindFirstInString
primitiveCompressToByteArray
- ba should be bounds checked
- bm is int*, but it probably should be unsigned int* because of the right shifts
primitiveDecompressFromByteArray
- bm is int*, but it should probably be unsigned int* as the method stores unsigned ints (data) into it
- index should be bounds checked (1 .. end)
- i, k, end and pastEnd should be unsigned int
primitiveFindFirstInString
- inclustionMap should be unsigned char* (in practice it's a ByteArray with 0-1 values)
primitiveIndexOfAsciiInString
- start can be 0 or negative. Either the loop should start from (start - 1 max: 0) or there should be an error if start is 0 or negative
- anInteger should be bounds checked (0 .. 255)
primitiveStringHash
- speciesHash should probably be unsigned int
primitiveTranslateStringWithTable
- start and stop need bounds checks (0 .. aString size - 1)
- the size of table should be checked to be 256

Levente

On Thu, 22 Feb 2018, Eliot Miranda wrote:

> 
> Hi Levente,
>
>    I really appreciate you taking a look.  I will say that the rewrite tried the stay as close to the originals while changing 1-relative indexing to 0-relative.  But I think we can also improve on the originals.  Indeed I spotted and fixed a potential bounds violation in primitiveConvert8Bit that only checked the size of one of the two array arguments.
>
> So can I ask you to read the primitives in the previous commit too?  Let's polish these a little :-)
>
> _,,,^..^,,,_ (phone)
>
>> On Feb 22, 2018, at 3:14 PM, Levente Uzonyi <leves at caesar.elte.hu> wrote:
>> 
>> Just had a look at this snippet, and wrote some quick inline comments.
>> 
>>> On Thu, 22 Feb 2018, commits at source.squeak.org wrote:
>>> 
>>> Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
>>> http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2338.mcz
>>> 
>>> ==================== Summary ====================
>>> 
>>> Name: VMMaker.oscog-eem.2338
>>> Author: eem
>>> Time: 22 February 2018, 10:25:17.794166 am
>>> UUID: 1672c678-41b4-41f2-a061-e201562fc75c
>>> Ancestors: VMMaker.oscog-eem.2337
>>> 
>>> Fix a slip in primitiveDecompressFromByteArray caught by IncludedMethodsTests.  Thank you David!
>>> 
>>> =============== Diff against VMMaker.oscog-eem.2337 ===============
>>> 
>>> Item was changed:
>>> ----- Method: MiscPrimitivePlugin>>primitiveDecompressFromByteArray (in category 'primitives') -----
>>> primitiveDecompressFromByteArray
>>>    "Bitmap decompress: bm fromByteArray: ba at: index"
>>>    <export: true>
>>>    | bm ba index i anInt code data end k n pastEnd |
>>>    <var: 'ba' type: #'unsigned char *'>
>>>    <var: 'bm' type: #'int *'>
>>>    <var: 'anInt' type: #'unsigned int'>
>>>    <var: 'code' type: #'unsigned int'>
>>>    <var: 'data' type: #'unsigned int'>
>>>    <var: 'n' type: #'unsigned int'>
>> 
>> Shouldn't i be declared as unsigned int too? It's used for indexing.
>>
>>>    bm := self cCode: [interpreterProxy arrayValueOf: (interpreterProxy stackValue: 2)]
>>>                inSmalltalk: [interpreterProxy
>>>                                cCoerce: (interpreterProxy arrayValueOf: (interpreterProxy stackValue: 2))
>>>                                to: #'int *'].
>>>    (interpreterProxy isOopImmutable: (interpreterProxy stackValue: 2)) ifTrue:
>>>        [^interpreterProxy primitiveFailFor: PrimErrNoModification].
>>>    (interpreterProxy isBytes: (interpreterProxy stackValue: 1)) ifFalse: [^interpreterProxy primitiveFail].
>>>    ba := interpreterProxy firstIndexableField: (interpreterProxy stackValue: 1).
>>>    index := interpreterProxy stackIntegerValue: 0.
>> 
>> Can index be negative or 0? If yes, then the value of i will be negative (unless it's implicit type is unsigned) and that will result in out of bounds indexing into ba a few lines below here.
>>
>>>    interpreterProxy failed ifTrue: [^nil].
>>>    i := index - 1.
>>>    k := 0.
>>>    end := interpreterProxy sizeOfSTArrayFromCPrimitive: ba.
>>>    pastEnd := interpreterProxy sizeOfSTArrayFromCPrimitive: bm.
>>>    [i < end] whileTrue:
>>>        [anInt := ba at: i.
>>>        i := i + 1.
>>>        anInt <= 223 ifFalse:
>>>            [anInt <= 254
>>>                ifTrue:
>>>                    [anInt := anInt - 224 * 256 + (ba at: i).
>> 
>> I would use bitShift: 8 instead of * 256, just to be consistent with the rest of the method.
>>
>>>                    i := i + 1]
>>>                ifFalse:
>>>                    [anInt := 0.
>>>                    1 to: 4 by: 1 do:
>>>                        [ :j | anInt := (anInt bitShift: 8) + (ba at: i).
>>>                        i := i + 1]]].
>>>        n := anInt >> 2.
>>> +        k + n > pastEnd ifTrue: [^interpreterProxy primitiveFail].
>>> -        k + n >= pastEnd ifTrue: [^interpreterProxy primitiveFail].
>>>        code := anInt bitAnd: 3.
>>>        "code = 0 ifTrue: [nil]."
>>>        code = 1 ifTrue:
>>>            [data := ba at: i.
>>>            i := i + 1.
>>>            data := data bitOr: (data bitShift: 8).
>>>            data := data bitOr: (data bitShift: 16).
>> 
>> I don't know what the point of this part of the code is, but I think the above 4 lines could read:
>> 
>> [data := 16r10101 * (ba at: i).
>> i := i + 1.
>> 
>> Levente
>>
>>>            1 to: n do:
>>>                [ :j |
>>>                bm at: k put: data.
>>>                k := k + 1]].
>>>        code = 2 ifTrue:
>>>            [data := 0.
>>>            1 to: 4 do:
>>>                [ :j |
>>>                data := (data bitShift: 8) bitOr: (ba at: i).
>>>                i := i + 1].
>>>            1 to: n do:
>>>                [ :j |
>>>                bm at: k put: data.
>>>                k := k + 1]].
>>>        code = 3 ifTrue:
>>>            [1 to: n do:
>>>                [ :m |
>>>                data := 0.
>>>                1 to: 4 do:
>>>                    [ :j |
>>>                    data := (data bitShift: 8) bitOr: (ba at: i).
>>>                    i := i + 1].
>>>                bm at: k put: data.
>>>                k := k + 1]]].
>>>    interpreterProxy pop: interpreterProxy methodArgumentCount!


More information about the Vm-dev mailing list