[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Numeric key collision related bug in Lua 5.3
- From: Coda Highland <chighland@...>
- Date: Tue, 21 Apr 2015 12:19:52 -0700
On Tue, Apr 21, 2015 at 11:54 AM, Dirk Laurie <dirk.laurie@gmail.com> wrote:
> 2015-04-21 18:36 GMT+02:00 Dirk Laurie <dirk.laurie@gmail.com>:
>> 2015-04-21 17:32 GMT+02:00 Egor Skriptunoff <egor.skriptunoff@gmail.com>:
>>> An interesting bug has been found in Lua 5.3
>>>
>>> t = {[(1<<63)-333] = 0}
>>> key = next(t) + 0.0
>>> t[key] = "Lua is great!"
>>> print(t[key]) --> Lua is great!
>>> t[0] = "Are you sure?"
>>> print(t[key]) --> nil
>>>
>>> Why Lua is not great anymore?
>>
>> The manual says:
>>
>> The indexing of tables follows the definition of raw equality in the
>> language. The expressions a[i] and a[j] denote the same table element
>> if and only if i and j are raw equal (that is, equal without
>> metamethods). In particular, floats with integral values are equal to
>> their respective integers (e.g., 1.0 == 1). To avoid ambiguities, any
>> float with integral value used as a key is converted to its respective
>> integer. For instance, if you write a[2.0] = true, the actual key
>> inserted into the table will be the integer 2. (On the other hand, 2
>> and "2" are different Lua values and therefore denote different table
>> entries.)
>>
>> Let origkey = 1<<63)-333, which is a very large integer, but slightly
>> smaller than math.maxinteger.
>>
>> "key" is a float with integral value, but that integral value is not
>> origkey, but math.maxinteger. In a floating-point comparison, it tests
>> equal to origkey,
>> though.
>>
>> When t[key] is assigned, "key" is not considered to be a new index, and
>> the value of t[origkey] is replaced.
>>
>> When t[0] is assigned, the hash part of the table is reorganized.
>> t[origkey] is still "Lua is great!", but is no longer found when asking
>> for t[key].
>
> I've been asking myself what in all this is a bug. And the answer has
> nothing to do with tables.
>
> origkey = (1<<63)-333
> maxint = math.maxinteger
> key = origkey + 0.
> print (maxint == key ) --> true
>
> I.e. a float that can be represented exactly as an integer is being
> compared to an integer is being compared to another integer,
> and tests equal even though those integers are different.
>
> Somewhat surprisingly, this is in fact the documented behaviour.
>
> | If both operands are integers, they are compared as integers;
> | otherwise, they are converted to floats and compared as such.
>
> The ideal solution would be to change the semantics to:
>
> | If both operands are integers, or if one operand is a float but
> | can be represented exactly as an integer, they are compared
> | as integers; otherwise, they are converted to floats and
> | compared as such.
>
> But until such time as that is done, I submit that the "numeric
> key collision related bug" is not a bug, but only a gotcha.
>
It won't be done. It would add load to the computational fast path
that isn't necessary in nearly all cases.
/s/ Adam