Better warnings for out-of-range values
Issue better warnings for out-of-range values. This is not yet complete. In particular, note we may have out-of-range for values that end up being subject to optimization. That is because the optimization takes place on the *truncated* value, not the pre-truncated value. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
parent
733cbb3197
commit
e9d7f1a074
4 changed files with 42 additions and 64 deletions
72
assemble.c
72
assemble.c
|
@ -185,13 +185,14 @@ static const char *size_name(int size)
|
|||
}
|
||||
}
|
||||
|
||||
static void warn_overflow(int size, int64_t data)
|
||||
static void warn_overflow(int size, const struct operand *o)
|
||||
{
|
||||
if (size < 8) {
|
||||
if (size < 8 && o->wrt == NO_SEG && o->segment == NO_SEG) {
|
||||
int64_t lim = ((int64_t)1 << (size*8))-1;
|
||||
int64_t data = o->offset;
|
||||
|
||||
if (data < ~lim || data > lim)
|
||||
errfunc(ERR_WARNING | ERR_WARN_NOV,
|
||||
errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
|
||||
"%s data exceeds bounds", size_name(size));
|
||||
}
|
||||
}
|
||||
|
@ -474,21 +475,21 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
|
|||
break;
|
||||
case R_CS:
|
||||
if (bits == 64) {
|
||||
error(ERR_WARNING,
|
||||
error(ERR_WARNING | ERR_PASS2,
|
||||
"cs segment base generated, but will be ignored in 64-bit mode");
|
||||
}
|
||||
c = 0x2E;
|
||||
break;
|
||||
case R_DS:
|
||||
if (bits == 64) {
|
||||
error(ERR_WARNING,
|
||||
error(ERR_WARNING | ERR_PASS2,
|
||||
"ds segment base generated, but will be ignored in 64-bit mode");
|
||||
}
|
||||
c = 0x3E;
|
||||
break;
|
||||
case R_ES:
|
||||
if (bits == 64) {
|
||||
error(ERR_WARNING,
|
||||
error(ERR_WARNING | ERR_PASS2,
|
||||
"es segment base generated, but will be ignored in 64-bit mode");
|
||||
}
|
||||
c = 0x26;
|
||||
|
@ -501,7 +502,7 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
|
|||
break;
|
||||
case R_SS:
|
||||
if (bits == 64) {
|
||||
error(ERR_WARNING,
|
||||
error(ERR_WARNING | ERR_PASS2,
|
||||
"ss segment base generated, but will be ignored in 64-bit mode");
|
||||
}
|
||||
c = 0x36;
|
||||
|
@ -744,8 +745,7 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
|
|||
static bool possible_sbyte(operand *o)
|
||||
{
|
||||
return !(o->opflags & OPFLAG_FORWARD) &&
|
||||
optimizing >= 0 && !(o->type & STRICT) &&
|
||||
o->wrt == NO_SEG && o->segment == NO_SEG;
|
||||
optimizing >= 0 && !(o->type & STRICT);
|
||||
}
|
||||
|
||||
/* check that opn[op] is a signed byte of size 16 or 32 */
|
||||
|
@ -771,23 +771,29 @@ static bool is_sbyte32(operand *o)
|
|||
return v >= -128 && v <= 127;
|
||||
}
|
||||
|
||||
/* check that opn[op] is a signed byte of size 32; warn if this is not
|
||||
/* check that opn[op] is a signed byte of size 32; warn if this is not
|
||||
the original value when extended to 64 bits */
|
||||
static bool is_sbyte64(operand *o)
|
||||
{
|
||||
int64_t v64;
|
||||
int32_t v32;
|
||||
int32_t v;
|
||||
|
||||
if (!(o->wrt == NO_SEG && o->segment == NO_SEG))
|
||||
return false; /* Not a pure immediate */
|
||||
|
||||
v64 = o->offset;
|
||||
v = (int32_t)v64;
|
||||
|
||||
if (v64 != v)
|
||||
errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
|
||||
"signed dword immediate exceeds bounds");
|
||||
|
||||
/* dead in the water on forward reference or External */
|
||||
if (!possible_sbyte(o))
|
||||
return false;
|
||||
|
||||
v64 = o->offset;
|
||||
v32 = (int32_t)v64;
|
||||
|
||||
warn_overflow(32, v64);
|
||||
|
||||
return v32 >= -128 && v32 <= 127;
|
||||
v = o->offset;
|
||||
return v >= -128 && v <= 127;
|
||||
}
|
||||
static int64_t calcsize(int32_t segment, int64_t offset, int bits,
|
||||
insn * ins, const uint8_t *codes)
|
||||
|
@ -1265,7 +1271,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
if (((opx->type & BITS8) ||
|
||||
!(opx->type & temp->opd[c & 3] & BYTENESS)) &&
|
||||
(opx->offset < -128 || opx->offset > 127)) {
|
||||
errfunc(ERR_WARNING | ERR_WARN_NOV,
|
||||
errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
|
||||
"signed byte value exceeds bounds");
|
||||
}
|
||||
if (opx->segment != NO_SEG) {
|
||||
|
@ -1285,7 +1291,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
case 022:
|
||||
case 023:
|
||||
if (opx->offset < -256 || opx->offset > 255) {
|
||||
errfunc(ERR_WARNING | ERR_WARN_NOV,
|
||||
errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
|
||||
"byte value exceeds bounds");
|
||||
}
|
||||
if (opx->segment != NO_SEG) {
|
||||
|
@ -1305,7 +1311,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
case 026:
|
||||
case 027:
|
||||
if (opx->offset < 0 || opx->offset > 255)
|
||||
errfunc(ERR_WARNING | ERR_WARN_NOV,
|
||||
errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
|
||||
"unsigned byte value exceeds bounds");
|
||||
if (opx->segment != NO_SEG) {
|
||||
data = opx->offset;
|
||||
|
@ -1323,9 +1329,8 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
case 031:
|
||||
case 032:
|
||||
case 033:
|
||||
warn_overflow(2, opx);
|
||||
data = opx->offset;
|
||||
if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
|
||||
warn_overflow(2, data);
|
||||
out(offset, segment, &data, OUT_ADDRESS, 2,
|
||||
opx->segment, opx->wrt);
|
||||
offset += 2;
|
||||
|
@ -1339,9 +1344,8 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
size = (opx->type & BITS16) ? 2 : 4;
|
||||
else
|
||||
size = (bits == 16) ? 2 : 4;
|
||||
warn_overflow(size, opx);
|
||||
data = opx->offset;
|
||||
if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
|
||||
warn_overflow(size, data);
|
||||
out(offset, segment, &data, OUT_ADDRESS, size,
|
||||
opx->segment, opx->wrt);
|
||||
offset += size;
|
||||
|
@ -1351,9 +1355,8 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
case 041:
|
||||
case 042:
|
||||
case 043:
|
||||
warn_overflow(4, opx);
|
||||
data = opx->offset;
|
||||
if (opx->segment == NO_SEG && opx->wrt == NO_SEG)
|
||||
warn_overflow(4, data);
|
||||
out(offset, segment, &data, OUT_ADDRESS, 4,
|
||||
opx->segment, opx->wrt);
|
||||
offset += 4;
|
||||
|
@ -1365,9 +1368,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
case 047:
|
||||
data = opx->offset;
|
||||
size = ins->addr_size >> 3;
|
||||
if (opx->segment == NO_SEG &&
|
||||
opx->wrt == NO_SEG)
|
||||
warn_overflow(size, data);
|
||||
warn_overflow(size, opx);
|
||||
out(offset, segment, &data, OUT_ADDRESS, size,
|
||||
opx->segment, opx->wrt);
|
||||
offset += size;
|
||||
|
@ -1472,15 +1473,13 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
case 0142:
|
||||
case 0143:
|
||||
data = opx->offset;
|
||||
warn_overflow(2, opx);
|
||||
if (is_sbyte16(opx)) {
|
||||
bytes[0] = data;
|
||||
out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
|
||||
NO_SEG);
|
||||
offset++;
|
||||
} else {
|
||||
if (opx->segment == NO_SEG &&
|
||||
opx->wrt == NO_SEG)
|
||||
warn_overflow(2, data);
|
||||
out(offset, segment, &data, OUT_ADDRESS, 2,
|
||||
opx->segment, opx->wrt);
|
||||
offset += 2;
|
||||
|
@ -1504,6 +1503,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
case 0152:
|
||||
case 0153:
|
||||
data = opx->offset;
|
||||
warn_overflow(4, opx);
|
||||
if (is_sbyte32(opx)) {
|
||||
bytes[0] = data;
|
||||
out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
|
||||
|
@ -1559,7 +1559,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
c & 7);
|
||||
} else {
|
||||
if (opx->offset & ~15) {
|
||||
errfunc(ERR_WARNING | ERR_WARN_NOV,
|
||||
errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
|
||||
"four-bit argument exceeds bounds");
|
||||
}
|
||||
bytes[0] |= opx->offset & 15;
|
||||
|
@ -1590,8 +1590,8 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
case 0252:
|
||||
case 0253:
|
||||
data = opx->offset;
|
||||
/* is_sbyte32() is right here, we have already warned */
|
||||
if (is_sbyte32(opx)) {
|
||||
warn_overflow(4, opx);
|
||||
if (is_sbyte64(opx)) {
|
||||
bytes[0] = data;
|
||||
out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG,
|
||||
NO_SEG);
|
||||
|
@ -1839,7 +1839,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
|
|||
case 2:
|
||||
case 4:
|
||||
data = ins->oprs[(c >> 3) & 7].offset;
|
||||
warn_overflow(ea_data.bytes, data);
|
||||
warn_overflow(ea_data.bytes, opx);
|
||||
out(offset, segment, &data,
|
||||
ea_data.rip ? OUT_REL4ADR : OUT_ADDRESS,
|
||||
ea_data.bytes,
|
||||
|
|
24
insns.dat
24
insns.dat
|
@ -61,11 +61,8 @@ ADC rm16,imm8 \320\1\x83\202\15 8086
|
|||
ADC rm32,imm8 \321\1\x83\202\15 386
|
||||
ADC rm64,imm8 \324\1\x83\202\15 X64
|
||||
ADC reg_al,imm \1\x14\21 8086,SM
|
||||
ADC reg_ax,sbyte16 \320\1\x83\202\15 8086,SM,ND
|
||||
ADC reg_ax,imm \320\1\x15\31 8086,SM
|
||||
ADC reg_eax,sbyte32 \321\1\x83\202\15 386,SM,ND
|
||||
ADC reg_eax,imm \321\1\x15\41 386,SM
|
||||
ADC reg_rax,sbyte64 \324\1\x83\202\15 X64,SM,ND
|
||||
ADC reg_rax,imm \324\1\x15\41 X64,SM
|
||||
ADC rm8,imm \1\x80\202\21 8086,SM
|
||||
ADC rm16,imm \320\145\x81\202\141 8086,SM
|
||||
|
@ -94,11 +91,8 @@ ADD rm16,imm8 \320\1\x83\200\15 8086
|
|||
ADD rm32,imm8 \321\1\x83\200\15 386
|
||||
ADD rm64,imm8 \324\1\x83\200\15 X64
|
||||
ADD reg_al,imm \1\x04\21 8086,SM
|
||||
ADD reg_ax,sbyte16 \320\1\x83\200\15 8086,SM,ND
|
||||
ADD reg_ax,imm \320\1\x05\31 8086,SM
|
||||
ADD reg_eax,sbyte32 \321\1\x83\200\15 386,SM,ND
|
||||
ADD reg_eax,imm \321\1\x05\41 386,SM
|
||||
ADD reg_rax,sbyte64 \324\1\x83\200\15 X64,SM,ND
|
||||
ADD reg_rax,imm \324\1\x05\41 X64,SM
|
||||
ADD rm8,imm \1\x80\200\21 8086,SM
|
||||
ADD rm16,imm \320\145\x81\200\141 8086,SM
|
||||
|
@ -127,11 +121,8 @@ AND rm16,imm8 \320\1\x83\204\15 8086
|
|||
AND rm32,imm8 \321\1\x83\204\15 386
|
||||
AND rm64,imm8 \324\1\x83\204\15 X64
|
||||
AND reg_al,imm \1\x24\21 8086,SM
|
||||
AND reg_ax,sbyte16 \320\1\x83\204\15 8086,SM,ND
|
||||
AND reg_ax,imm \320\1\x25\31 8086,SM
|
||||
AND reg_eax,sbyte32 \321\1\x83\204\15 386,SM,ND
|
||||
AND reg_eax,imm \321\1\x25\41 386,SM
|
||||
AND reg_rax,sbyte64 \324\1\x83\204\15 X64,SM,ND
|
||||
AND reg_rax,imm \324\1\x25\41 X64,SM
|
||||
AND rm8,imm \1\x80\204\21 8086,SM
|
||||
AND rm16,imm \320\145\x81\204\141 8086,SM
|
||||
|
@ -255,11 +246,8 @@ CMP rm16,imm8 \320\1\x83\207\15 8086
|
|||
CMP rm32,imm8 \321\1\x83\207\15 386
|
||||
CMP rm64,imm8 \324\1\x83\207\15 X64
|
||||
CMP reg_al,imm \1\x3C\21 8086,SM
|
||||
CMP reg_ax,sbyte16 \320\1\x83\207\15 8086,SM,ND
|
||||
CMP reg_ax,imm \320\1\x3D\31 8086,SM
|
||||
CMP reg_eax,sbyte32 \321\1\x83\207\15 386,SM,ND
|
||||
CMP reg_eax,imm \321\1\x3D\41 386,SM
|
||||
CMP reg_rax,sbyte64 \324\1\x83\207\15 X64,SM,ND
|
||||
CMP reg_rax,imm \324\1\x3D\41 X64,SM
|
||||
CMP rm8,imm \1\x80\207\21 8086,SM
|
||||
CMP rm16,imm \320\145\x81\207\141 8086,SM
|
||||
|
@ -856,11 +844,8 @@ OR rm16,imm8 \320\1\x83\201\15 8086
|
|||
OR rm32,imm8 \321\1\x83\201\15 386
|
||||
OR rm64,imm8 \324\1\x83\201\15 X64
|
||||
OR reg_al,imm \1\x0C\21 8086,SM
|
||||
OR reg_ax,sbyte16 \320\1\x83\201\15 8086,SM,ND
|
||||
OR reg_ax,imm \320\1\x0D\31 8086,SM
|
||||
OR reg_eax,sbyte32 \321\1\x83\201\15 386,SM,ND
|
||||
OR reg_eax,imm \321\1\x0D\41 386,SM
|
||||
OR reg_rax,sbyte64 \324\1\x83\201\15 X64,SM,ND
|
||||
OR reg_rax,imm \324\1\x0D\41 X64,SM
|
||||
OR rm8,imm \1\x80\201\21 8086,SM
|
||||
OR rm16,imm \320\145\x81\201\141 8086,SM
|
||||
|
@ -1111,11 +1096,8 @@ SBB rm16,imm8 \320\1\x83\203\15 8086
|
|||
SBB rm32,imm8 \321\1\x83\203\15 386
|
||||
SBB rm64,imm8 \324\1\x83\203\15 X64
|
||||
SBB reg_al,imm \1\x1C\21 8086,SM
|
||||
SBB reg_ax,sbyte16 \320\1\x83\203\15 8086,SM,ND
|
||||
SBB reg_ax,imm \320\1\x1D\31 8086,SM
|
||||
SBB reg_eax,sbyte32 \321\1\x83\203\15 386,SM,ND
|
||||
SBB reg_eax,imm \321\1\x1D\41 386,SM
|
||||
SBB reg_rax,sbyte64 \324\1\x83\203\15 X64,SM,ND
|
||||
SBB reg_rax,imm \324\1\x1D\41 X64,SM
|
||||
SBB rm8,imm \1\x80\203\21 8086,SM
|
||||
SBB rm16,imm \320\145\x81\203\141 8086,SM
|
||||
|
@ -1227,11 +1209,8 @@ SUB rm16,imm8 \320\1\x83\205\15 8086
|
|||
SUB rm32,imm8 \321\1\x83\205\15 386
|
||||
SUB rm64,imm8 \324\1\x83\205\15 X64
|
||||
SUB reg_al,imm \1\x2C\21 8086,SM
|
||||
SUB reg_ax,sbyte16 \320\1\x83\205\15 8086,SM,ND
|
||||
SUB reg_ax,imm \320\1\x2D\31 8086,SM
|
||||
SUB reg_eax,sbyte32 \321\1\x83\205\15 386,SM,ND
|
||||
SUB reg_eax,imm \321\1\x2D\41 386,SM
|
||||
SUB reg_rax,sbyte64 \324\1\x83\205\15 X64,SM,ND
|
||||
SUB reg_rax,imm \324\1\x2D\41 X64,SM
|
||||
SUB rm8,imm \1\x80\205\21 8086,SM
|
||||
SUB rm16,imm \320\145\x81\205\141 8086,SM
|
||||
|
@ -1358,11 +1337,8 @@ XOR rm16,imm8 \320\1\x83\206\15 8086
|
|||
XOR rm32,imm8 \321\1\x83\206\15 386
|
||||
XOR rm64,imm8 \324\1\x83\206\15 X64
|
||||
XOR reg_al,imm \1\x34\21 8086,SM
|
||||
XOR reg_ax,sbyte16 \320\1\x83\206\15 8086,SM,ND
|
||||
XOR reg_ax,imm \320\1\x35\31 8086,SM
|
||||
XOR reg_eax,sbyte32 \321\1\x83\206\15 386,SM,ND
|
||||
XOR reg_eax,imm \321\1\x35\41 386,SM
|
||||
XOR reg_rax,sbyte64 \324\1\x83\206\15 X64,SM,ND
|
||||
XOR reg_rax,imm \324\1\x35\41 X64,SM
|
||||
XOR rm8,imm \1\x80\206\21 8086,SM
|
||||
XOR rm16,imm \320\145\x81\206\141 8086,SM
|
||||
|
|
3
nasm.c
3
nasm.c
|
@ -1888,7 +1888,8 @@ static bool is_suppressed_warning(int severity)
|
|||
(((severity & ERR_WARN_MASK) != 0 &&
|
||||
!warning_on[(severity & ERR_WARN_MASK) >> ERR_WARN_SHR]) ||
|
||||
/* See if it's a pass-one only warning and we're not in pass one. */
|
||||
((severity & ERR_PASS1) && pass0 != 1));
|
||||
((severity & ERR_PASS1) && pass0 != 1) ||
|
||||
((severity & ERR_PASS2) && pass0 != 2));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -71,14 +71,15 @@ extern efunc nasm_malloc_error;
|
|||
#define ERR_NOFILE 0x00000010 /* don't give source file name/line */
|
||||
#define ERR_USAGE 0x00000020 /* print a usage message */
|
||||
#define ERR_PASS1 0x00000040 /* only print this error on pass one */
|
||||
#define ERR_NO_SEVERITY 0x00000080 /* suppress printing severity */
|
||||
#define ERR_PASS2 0x00000080
|
||||
#define ERR_NO_SEVERITY 0x00000100 /* suppress printing severity */
|
||||
|
||||
/*
|
||||
* These codes define specific types of suppressible warning.
|
||||
*/
|
||||
|
||||
#define ERR_WARN_MASK 0x0000FF00 /* the mask for this feature */
|
||||
#define ERR_WARN_SHR 8 /* how far to shift right */
|
||||
#define ERR_WARN_MASK 0xFFFFF000 /* the mask for this feature */
|
||||
#define ERR_WARN_SHR 12 /* how far to shift right */
|
||||
|
||||
#define WARN(x) ((x) << ERR_WARN_SHR)
|
||||
|
||||
|
|
Loading…
Reference in a new issue