Jure Bagić
unread,Dec 11, 2025, 11:03:34 AM (5 days ago) Dec 11Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to lua-l
potential bug
Message-ID: <daz4z63fabayrhruby4tkislbezypbmxvrtr4r2iivbwtlfh6g@qtitqh3b7dma>
Reply-To:
In ldebug.c:562:
> return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
LUA_ENV might have multiple '\0'. When constructing literal strings Lua takes
the size of the literal which would include the embedded '\0', as it should.
However 'strcmp' might prematurely stop comparing bytes in 'name' and
'LUA_ENV'.
This is the definition of 'strcmp' in libmusl:
> int strcmp(const char *l, const char *r)
> {
> for (; *l==*r && *l; l++, r++);
> return *(unsigned char *)l - *(unsigned char *)r;
> }
Same for the unreadable glibc when comparing unaligned bytes of 'p1':
> int
> strcmp (const char *p1, const char *p2)
> {
> /* Handle the unaligned bytes of p1 first. */
> uintptr_t n = -(uintptr_t)p1 % sizeof(op_t);
> for (int i = 0; i < n; ++i)
> {
> unsigned char c1 = *p1++;
> unsigned char c2 = *p2++;
> int diff = c1 - c2;
> if (c1 == '\0' || diff != 0)
> return diff;
> }
>
> /* P1 is now aligned to op_t. P2 may or may not be. */
> const op_t *x1 = (const op_t *) p1;
> op_t w1 = *x1++;
> uintptr_t ofs = (uintptr_t) p2 % sizeof(op_t);
> return ofs == 0
> ? strcmp_aligned_loop (x1, (const op_t *)p2, w1)
> : strcmp_unaligned_loop (x1, (const op_t *)(p2 - ofs), w1, ofs);
> }
Let's say 'name' is "bo\0" and LUA_ENV is "bo\0gus".
The 'strcmp(name, LUA_ENV)' would return 0 because it would stop comparing at
'\0' but the strings are obviously not the same. Additionally, inverse could
occur if the upvalue name somehow had embedded '\0' in it (although this is not
exposed in the C API nor is it a valid syntax).
-- Jure