• Subject: Re: Numeric key collision related bug in Lua 5.3
• From: Tim Hill <drtimhill@...>
• Date: Tue, 21 Apr 2015 12:20:23 -0700

```> On Apr 21, 2015, at 9:36 AM, Dirk Laurie <dirk.laurie@gmail.com> wrote:
>
> 2015-04-21 17:32 GMT+02:00 Egor Skriptunoff <egor.skriptunoff@gmail.com>:
>> Hi!
>>
>> 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].
>

Hmm this still looks like a bug to me. The entire hash/non-hash parts of tables are supposed to be purely implementation detail, yet here we are seeing the insertion of t[0] causing behavior changes to unrelated key(s). I’m not even sure what Lua is doing with that key, what does “float with integral value” mean for an integer that has no exact representation as a double-precision float (i.e. is > 2^52)?

nkey = (1<<63)-333
fkey = nkey + 0.0
print(fkey == nkey)		-> true

t = {}
t[nkey] = “nkey”
t[fkey] = “fkey”
print(t[nkey], t[fkey])	-> “fkey” “fkey”		— Expected based on equality check above

t[0] = 0
print(t[nkey], t[fkey])	-> “fkey” nil		— Unexpected

—Tim

```

• Follow-Ups: