An unsigned overflow in luai_makeseed()

36 views
Skip to first unread message

Sergey Bronnikov

unread,
Feb 17, 2026, 4:50:39 AM (3 days ago) Feb 17
to lua-l
Hello,

the function luai_makeseed() in lauxlib.c has the following expression [1]:

res ^= (res >> 3) + (res << 7) + buff[i];

where res has type "unsigned integer". This arithmetic has an unsigned overflow.
This is of course undefined behavior from a language point of view, but maybe it is used here intentionally?

Błażej Roszkowski

unread,
Feb 17, 2026, 5:04:07 AM (3 days ago) Feb 17
to lu...@googlegroups.com
AFAIK unsigned overflow is and always was defined in both C and C++ to just be modulo arithmetics.

--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/lua-l/c36ec376-99a3-4869-9881-46eb9dde1a6cn%40googlegroups.com.

Francisco Olarte

unread,
Feb 17, 2026, 5:04:29 AM (3 days ago) Feb 17
to lu...@googlegroups.com
Hi Sergey:

On Tue, 17 Feb 2026 at 10:50, Sergey Bronnikov <est...@gmail.com> wrote:
the function luai_makeseed() in lauxlib.c has the following expression [1]:
res ^= (res >> 3) + (res << 7) + buff[i];
where res has type "unsigned integer". This arithmetic has an unsigned overflow.
This is of course undefined behavior from a language point of view, but maybe it is used here intentionally?

My C is a bit rusty, but IIRC in C/C++ unsigned overflow is defined to be modulo 2^n, signed overflow is the one with nasal demons risk.

( that code is a classic way to do bit mixing expecting wraparound ).

Francisco Olarte.

Андрей Закатов

unread,
Feb 17, 2026, 5:08:46 AM (3 days ago) Feb 17
to lu...@googlegroups.com
AFAIK it's the signed overflow that is considered UB, and unsigned operations are defined with modular arithmetic, no?

Yao Zi

unread,
Feb 17, 2026, 7:39:19 AM (3 days ago) Feb 17
to lu...@googlegroups.com
On Tue, Feb 17, 2026 at 01:50:39AM -0800, Sergey Bronnikov wrote:
> Hello,
>
> the function luai_makeseed() in lauxlib.c has the following expression [1]:
>
> res ^= (res >> 3) + (res << 7) + buff[i];
>
> where res has type "unsigned integer". This arithmetic has an unsigned
> overflow.
> This is of course undefined behavior from a language point of view, but

If res has type "signed int", this is true, ISO 9899:1999 6.5.5 states

> If an exceptional condition occurs during the evaluation of an
> expression (that is, if the result is not mathematically defined or
> not in the range of representable values for its type), the behavior
> is undefined.

However res has type "unsigned int", and for unsigned types we have an
extra rule in 6.2.5.9,

> A computation involving unsigned operands can never overflow, because
> a result that cannot be represented by the resulting unsigned integer
> type is reduced modulo the number that is one greater than the largest
> value that can be represented by the resulting type.

So the behavior is of course defined :)

> maybe it is used here intentionally?

Sure, having the arithmetic result truncated isn't a problem here. We're
making a seed instead of calculating a specific value, what res is in
the end doesn't matter as long as it makes a good use of the entropy.

> 1. https://github.com/lua/lua/blob/c6b484823806e08e1756b1a6066a3ace6f080fae/lauxlib.c#L1167
>
> Sergey

Best regards,
Yao Zi
Reply all
Reply to author
Forward
0 new messages