https://sourceware.org/bugzilla/show_bug.cgi?id=34756
Bug ID: 34756
Summary: x86: far jmp/call with a constant offset wider than 32
bits is silently truncated
Product: binutils
Version: 2.48 (HEAD)
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: gas
Assignee: unassigned at sourceware dot org
Reporter: martin.mirchev at u dot nus.edu
Target Milestone: ---
In 32-bit code, a direct far jump or call whose constant offset does not fit
in 32 bits is assembled with the offset silently truncated, with no warning
or error. The 16-bit form is diagnosed ("16-bit jump out of range"), and an
oversized immediate in other instructions gets a "shortened" warning.
$ cat far.s
.code32
ljmp $0x10, $0x123456789
lcall $0x10, $0x100000000
$ as --32 far.s -o far.o && objdump -d far.o
0: ea 89 67 45 23 10 00 ljmp $0x10,$0x23456789
7: 9a 00 00 00 00 10 00 lcall $0x10,$0x0
For comparison:
.code16
ljmp $0x10, $0x123456 -> Error: 16-bit jump out of range
.code32
mov $0x123456789, %eax -> Warning: 0x123456789 shortened to
0x23456789
Cause: output_interseg_jump() in gas/config/tc-i386.c only range-checks the
constant offset when size == 2; for size == 4 it is passed straight to
md_number_to_chars().
Suggested fix (mirrors the existing 16-bit check):
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -12115,6 +12115,13 @@
as_bad (_("16-bit jump out of range"));
return;
}
+ if (size == 4
+ && !fits_in_unsigned_long (n)
+ && !fits_in_signed_long (n))
+ {
+ as_bad (_("32-bit jump out of range"));
+ return;
+ }
md_number_to_chars (p, n, size);
}
else
With the patch both lines above are rejected, in-range offsets are
unchanged, and assembling every gas/testsuite/gas/i386/*.s with --32 and
--64 produces identical objects and diagnostics to the unpatched assembler.
Seen with binutils 2.47; the same code is present on current master.
This issue was found by an LLM-Enhanced Static Analysis Engine and verified
manually.
--
You are receiving this mail because:
You are on the CC list for the bug.