Avoid negation of signed integers in C that may hold INT*_MIN.

Reported by minoki.
Recent C compilers 'take advantage' of the undefined behavior.
This completely changes the meaning of expressions like (k == -k).
This commit is contained in:
Mike Pall
2022-12-22 00:03:06 +01:00
parent b2791179ef
commit 8a5e398c52
12 changed files with 32 additions and 32 deletions

View File

@@ -951,22 +951,22 @@ static void bcemit_unop(FuncState *fs, BCOp op, ExpDesc *e)
#if LJ_HASFFI
if (e->k == VKCDATA) { /* Fold in-place since cdata is not interned. */
GCcdata *cd = cdataV(&e->u.nval);
int64_t *p = (int64_t *)cdataptr(cd);
uint64_t *p = (uint64_t *)cdataptr(cd);
if (cd->ctypeid == CTID_COMPLEX_DOUBLE)
p[1] ^= (int64_t)U64x(80000000,00000000);
p[1] ^= U64x(80000000,00000000);
else
*p = -*p;
*p = ~*p+1u;
return;
} else
#endif
if (expr_isnumk(e) && !expr_numiszero(e)) { /* Avoid folding to -0. */
TValue *o = expr_numtv(e);
if (tvisint(o)) {
int32_t k = intV(o);
if (k == -k)
int32_t k = intV(o), negk = (int32_t)(~(uint32_t)k+1u);
if (k == negk)
setnumV(o, -(lua_Number)k);
else
setintV(o, -k);
setintV(o, negk);
return;
} else {
o->u64 ^= U64x(80000000,00000000);