lint: detect more cases of integer overflow in constant expressions
For unsigned integers, detect when 'a + b' wraps around.
This commit is contained in:
parent
ee9f134f18
commit
51858eeb3e
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: expr_fold.c,v 1.13 2024/03/10 10:31:29 rillig Exp $ */
|
||||
/* $NetBSD: expr_fold.c,v 1.14 2024/03/10 14:32:30 rillig Exp $ */
|
||||
# 3 "expr_fold.c"
|
||||
|
||||
/*
|
||||
|
@ -59,8 +59,7 @@ fold_uminus(void)
|
|||
/* The '-' is an operator, it is not part of the integer constant. */
|
||||
take_int(-2147483648);
|
||||
|
||||
/* expect+2: warning: operator '+' produces integer overflow [141] */
|
||||
/* expect+1: warning: operator '-' produces integer overflow [141] */
|
||||
/* expect+1: warning: operator '+' produces integer overflow [141] */
|
||||
take_int(-(2147483647 + 1));
|
||||
/* expect+1: warning: operator '-' produces integer overflow [141] */
|
||||
take_int(-(-2147483647 - 1));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: msg_141.c,v 1.13 2024/03/10 10:31:29 rillig Exp $ */
|
||||
/* $NetBSD: msg_141.c,v 1.14 2024/03/10 14:32:30 rillig Exp $ */
|
||||
# 3 "msg_141.c"
|
||||
|
||||
// Test for message: operator '%s' produces integer overflow [141]
|
||||
|
@ -347,11 +347,11 @@ plus_u64(void)
|
|||
u64 = 0xffffffffffffffffULL + 0x0000000000000000ULL;
|
||||
u64 = 0x0000000000000000ULL + 0xffffffffffffffffULL;
|
||||
u64 = 0xfffffffffffffffeULL + 0x0000000000000001ULL;
|
||||
/* TODO: expect+1: warning: operator '+' produces integer overflow [141] */
|
||||
/* expect+1: warning: operator '+' produces integer overflow [141] */
|
||||
u64 = 0xffffffffffffffffULL + 0x0000000000000001ULL;
|
||||
/* TODO: expect+1: warning: operator '+' produces integer overflow [141] */
|
||||
/* expect+1: warning: operator '+' produces integer overflow [141] */
|
||||
u64 = 0x0000000000000001ULL + 0xffffffffffffffffULL;
|
||||
/* TODO: expect+1: warning: operator '+' produces integer overflow [141] */
|
||||
/* expect+1: warning: operator '+' produces integer overflow [141] */
|
||||
u64 = 0xffffffffffffffffULL + 0xffffffffffffffffULL;
|
||||
}
|
||||
|
||||
|
@ -374,12 +374,12 @@ void
|
|||
minus_u32(void)
|
||||
{
|
||||
u32 = 0x00000000U - 0x00000000U;
|
||||
/* TODO: expect+1: warning: operator '-' produces integer overflow [141] */
|
||||
/* expect+1: warning: operator '-' produces integer overflow [141] */
|
||||
u32 = 0x00000000U - 0x00000001U;
|
||||
/* expect+1: warning: operator '-' produces integer overflow [141] */
|
||||
u32 = 0x00000000U - 0x80000000U;
|
||||
u32 = 0x80000000U - 0x00000001U;
|
||||
/* TODO: expect+1: warning: operator '-' produces integer overflow [141] */
|
||||
/* expect+1: warning: operator '-' produces integer overflow [141] */
|
||||
u32 = 0x00000000U - 0xffffffffU;
|
||||
u32 = 0xffffffffU - 0x00000000U;
|
||||
u32 = 0xffffffffU - 0xffffffffU;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: tree.c,v 1.618 2024/03/10 12:50:45 rillig Exp $ */
|
||||
/* $NetBSD: tree.c,v 1.619 2024/03/10 14:32:30 rillig Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994, 1995 Jochen Pohl
|
||||
|
@ -37,7 +37,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(__RCSID)
|
||||
__RCSID("$NetBSD: tree.c,v 1.618 2024/03/10 12:50:45 rillig Exp $");
|
||||
__RCSID("$NetBSD: tree.c,v 1.619 2024/03/10 14:32:30 rillig Exp $");
|
||||
#endif
|
||||
|
||||
#include <float.h>
|
||||
|
@ -819,18 +819,12 @@ fold_unsigned_integer(op_t op, uint64_t l, uint64_t r,
|
|||
return 0;
|
||||
} else
|
||||
return l % r;
|
||||
case PLUS:;
|
||||
uint64_t plus_result = l + r;
|
||||
uint64_t hi = max_value ^ (max_value >> 1);
|
||||
if (l & hi && r & hi && !(plus_result & hi))
|
||||
*overflow = true;
|
||||
return plus_result;
|
||||
case MINUS:;
|
||||
uint64_t minus_result = l - r;
|
||||
hi = max_value ^ (max_value >> 1);
|
||||
if (!(l & hi) && r & hi && minus_result & hi)
|
||||
*overflow = true;
|
||||
return minus_result;
|
||||
case PLUS:
|
||||
*overflow = l > max_value - r;
|
||||
return l + r;
|
||||
case MINUS:
|
||||
*overflow = l < r;
|
||||
return l - r;
|
||||
case SHL:
|
||||
/* TODO: warn about out-of-bounds 'sr'. */
|
||||
return l << (r & 63);
|
||||
|
@ -910,23 +904,26 @@ fold_signed_integer(op_t op, int64_t l, int64_t r,
|
|||
return 0;
|
||||
}
|
||||
return l % r;
|
||||
case PLUS:;
|
||||
uint64_t plus_result = (uint64_t)l + (uint64_t)r;
|
||||
hi = (uint64_t)max_value + 1;
|
||||
|
||||
if (l & hi && r & hi && !(plus_result & hi))
|
||||
case PLUS:
|
||||
if (r > 0 && l > max_value - r) {
|
||||
*overflow = true;
|
||||
if (!(l & hi) && !(r & hi) && plus_result & hi)
|
||||
return max_value;
|
||||
}
|
||||
if (r < 0 && l < min_value - r) {
|
||||
*overflow = true;
|
||||
return (int64_t)plus_result;
|
||||
case MINUS:;
|
||||
uint64_t minus_result = (uint64_t)l - (uint64_t)r;
|
||||
hi = (uint64_t)max_value + 1;
|
||||
if (l & hi && !(r & hi) && !(minus_result & hi))
|
||||
return min_value;
|
||||
}
|
||||
return l + r;
|
||||
case MINUS:
|
||||
if (r > 0 && l < min_value + r) {
|
||||
*overflow = true;
|
||||
if (!(l & hi) && r & hi && minus_result & hi)
|
||||
return min_value;
|
||||
}
|
||||
if (r < 0 && l > max_value + r) {
|
||||
*overflow = true;
|
||||
return (int64_t)minus_result;
|
||||
return max_value;
|
||||
}
|
||||
return l - r;
|
||||
case SHL:
|
||||
/* TODO: warn about out-of-bounds 'sr'. */
|
||||
/* TODO: warn about overflow in signed '<<'. */
|
||||
|
|
Loading…
Reference in New Issue