[llvm] [X86AsmParser] Check displacement overflow (PR #75747)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 17 19:06:00 PST 2023


https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/75747

>From 9bc12efefed495484e51fd619f424c51fe612c64 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 17 Dec 2023 11:09:15 -0800
Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
 =?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.4
---
 .../lib/Target/X86/AsmParser/X86AsmParser.cpp | 27 ++++++++++
 llvm/test/MC/X86/displacement-overflow.s      | 36 +++++++++++++
 llvm/test/MC/X86/x86-64.s                     | 52 +++++++++----------
 llvm/test/MC/X86/x86_64-asm-match.s           |  6 +--
 llvm/test/MC/X86/x86_64-encoding.s            |  6 +--
 5 files changed, 95 insertions(+), 32 deletions(-)
 create mode 100644 llvm/test/MC/X86/displacement-overflow.s

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index e78d160564601c..ef622e08606cbf 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -3062,6 +3062,33 @@ bool X86AsmParser::ParseMemOperand(unsigned SegReg, const MCExpr *Disp,
                                       ErrMsg))
     return Error(BaseLoc, ErrMsg);
 
+  // If the displacement is a constant, check overflows. For 64-bit addressing,
+  // gas requires isInt<32> and otherwise reports an error. For others, gas
+  // reports a warning and allows a wider range. E.g. gas allows
+  // [-0xffffffff,0xffffffff] for 32-bit addressing (e.g. Linux kernel uses
+  // `leal -__PAGE_OFFSET(%ecx),%esp` where __PAGE_OFFSET is 0xc0000000).
+  if (BaseReg || IndexReg) {
+    if (auto CE = dyn_cast<MCConstantExpr>(Disp)) {
+      auto Imm = CE->getValue();
+      bool Is64 = X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg) ||
+                  X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg);
+      bool Is16 = X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg);
+      if (Is64) {
+        if (!isInt<32>(Imm))
+          return Error(BaseLoc, "displacement " + Twine(Imm) +
+                                    " is not within [-2147483648, 2147483647]");
+      } else if (!Is16) {
+        if (!isUInt<32>(Imm < 0 ? -uint64_t(Imm) : uint64_t(Imm))) {
+          Warning(BaseLoc,
+                  "displacement " + Twine(Imm) + " shortened to signed 32-bit");
+        }
+      } else if (!isUInt<16>(Imm < 0 ? -uint64_t(Imm) : uint64_t(Imm))) {
+        Warning(BaseLoc,
+                "displacement " + Twine(Imm) + " shortened to signed 16-bit");
+      }
+    }
+  }
+
   if (SegReg || BaseReg || IndexReg)
     Operands.push_back(X86Operand::CreateMem(getPointerWidth(), SegReg, Disp,
                                              BaseReg, IndexReg, Scale, StartLoc,
diff --git a/llvm/test/MC/X86/displacement-overflow.s b/llvm/test/MC/X86/displacement-overflow.s
new file mode 100644
index 00000000000000..626003a29109ea
--- /dev/null
+++ b/llvm/test/MC/X86/displacement-overflow.s
@@ -0,0 +1,36 @@
+# RUN: not llvm-mc -triple=x86_64 %s 2>&1 | FileCheck %s --check-prefixes=CHECK,64 --implicit-check-not=error: --implicit-check-not=warning:
+# RUN: llvm-mc -triple=i686 --defsym A16=1 %s 2>&1 | FileCheck %s --check-prefixes=CHECK,32 --implicit-check-not=error: --implicit-check-not=warning:
+
+.ifndef A16
+movq 0x80000000-1(%rip), %rax
+leaq -0x80000000(%rip), %rax
+
+# 64: [[#@LINE+1]]:17: error: displacement 2147483648 is not within [-2147483648, 2147483647]
+movq 0x80000000(%rip), %rax
+
+# 64: [[#@LINE+1]]:18: error: displacement -2147483649 is not within [-2147483648, 2147483647]
+leaq -0x80000001(%rip), %rax
+.endif
+
+movl 0xffffffff(%eax), %eax
+leal -0xffffffff(%eax), %eax
+
+# CHECK: [[#@LINE+1]]:19: warning: displacement 4294967296 shortened to signed 32-bit
+movl 0xffffffff+1(%eax), %eax
+
+# CHECK: [[#@LINE+1]]:20: warning: displacement -4294967296 shortened to signed 32-bit
+leal -0xffffffff-1(%eax), %eax
+
+{disp8} leal 0x100(%ebx), %eax
+{disp8} leal -0x100(%ebx), %eax
+
+.ifdef A16
+.code16
+movw $0, 0xffff(%bp)
+movw $0, -0xffff(%si)
+
+# 32: [[#@LINE+1]]:19: warning: displacement 65536 shortened to signed 16-bit
+movw $0, 0xffff+1(%bp)
+# 32: [[#@LINE+1]]:20: warning: displacement -65536 shortened to signed 16-bit
+movw $0, -0xffff-1(%si)
+.endif
diff --git a/llvm/test/MC/X86/x86-64.s b/llvm/test/MC/X86/x86-64.s
index 67b962c563eb57..108d1220107e33 100644
--- a/llvm/test/MC/X86/x86-64.s
+++ b/llvm/test/MC/X86/x86-64.s
@@ -346,11 +346,11 @@ fnstsw %ax
 
 // rdar://8431880
 // CHECK: rclb	%bl
-// CHECK: rcll	3735928559(%ebx,%ecx,8)
+// CHECK: rcll	2125315823(%ebx,%ecx,8)
 // CHECK: rcrl	%ecx
 // CHECK: rcrl	305419896
 rcl	%bl
-rcll	0xdeadbeef(%ebx,%ecx,8)
+rcll	0x7eadbeef(%ebx,%ecx,8)
 rcr	%ecx
 rcrl	0x12345678
 
@@ -573,9 +573,9 @@ leaq	8(%rax), %rsi
 // CHECK: encoding: [0x48,0x8d,0x70,0x08]
 
 
-cvttpd2dq	0xdeadbeef(%ebx,%ecx,8),%xmm5
-// CHECK: cvttpd2dq	3735928559(%ebx,%ecx,8), %xmm5
-// CHECK: encoding: [0x67,0x66,0x0f,0xe6,0xac,0xcb,0xef,0xbe,0xad,0xde]
+cvttpd2dq	0x7eadbeef(%ebx,%ecx,8),%xmm5
+// CHECK: cvttpd2dq	2125315823(%ebx,%ecx,8), %xmm5
+// CHECK: encoding: [0x67,0x66,0x0f,0xe6,0xac,0xcb,0xef,0xbe,0xad,0x7e]
 
 // rdar://8490728 - llvm-mc rejects 'movmskpd'
 movmskpd	%xmm6, %rax
@@ -906,8 +906,8 @@ xchgl   %ecx, 368(%rax)
 // CHECK: xchgl	%ecx, 368(%rax)
 
 // rdar://8407548
-xchg	0xdeadbeef(%rbx,%rcx,8),%bl
-// CHECK: xchgb	%bl, 3735928559(%rbx,%rcx,8)
+xchg	0x7fffffff(%rbx,%rcx,8),%bl
+// CHECK: xchgb	%bl, 2147483647(%rbx,%rcx,8)
 
 
 
@@ -1112,7 +1112,7 @@ mov %gs, (%rsi)  // CHECK: movw	%gs, (%rsi) # encoding: [0x8c,0x2e]
 //CHECK: divb	%bl
 //CHECK: divw	%bx
 //CHECK: divl	%ecx
-//CHECK: divl	3735928559(%ebx,%ecx,8)
+//CHECK: divl	2125315823(%ebx,%ecx,8)
 //CHECK: divl	69
 //CHECK: divl	32493
 //CHECK: divl	3133065982
@@ -1120,7 +1120,7 @@ mov %gs, (%rsi)  // CHECK: movw	%gs, (%rsi) # encoding: [0x8c,0x2e]
 //CHECK: idivb	%bl
 //CHECK: idivw	%bx
 //CHECK: idivl	%ecx
-//CHECK: idivl	3735928559(%ebx,%ecx,8)
+//CHECK: idivl	2125315823(%ebx,%ecx,8)
 //CHECK: idivl	69
 //CHECK: idivl	32493
 //CHECK: idivl	3133065982
@@ -1128,7 +1128,7 @@ mov %gs, (%rsi)  // CHECK: movw	%gs, (%rsi) # encoding: [0x8c,0x2e]
 	div	%bl,%al
 	div	%bx,%ax
 	div	%ecx,%eax
-	div	0xdeadbeef(%ebx,%ecx,8),%eax
+	div	0x7eadbeef(%ebx,%ecx,8),%eax
 	div	0x45,%eax
 	div	0x7eed,%eax
 	div	0xbabecafe,%eax
@@ -1136,7 +1136,7 @@ mov %gs, (%rsi)  // CHECK: movw	%gs, (%rsi) # encoding: [0x8c,0x2e]
 	idiv	%bl,%al
 	idiv	%bx,%ax
 	idiv	%ecx,%eax
-	idiv	0xdeadbeef(%ebx,%ecx,8),%eax
+	idiv	0x7eadbeef(%ebx,%ecx,8),%eax
 	idiv	0x45,%eax
 	idiv	0x7eed,%eax
 	idiv	0xbabecafe,%eax
@@ -1510,9 +1510,9 @@ vmovd %xmm0, %eax
 vmovd %xmm0, %rax
 vmovq %xmm0, %rax
 
-// CHECK: seto 3735928559(%r10,%r9,8)
-// CHECK:  encoding: [0x43,0x0f,0x90,0x84,0xca,0xef,0xbe,0xad,0xde]
-	seto 0xdeadbeef(%r10,%r9,8)
+// CHECK: seto 2125315823(%r10,%r9,8)
+// CHECK:  encoding: [0x43,0x0f,0x90,0x84,0xca,0xef,0xbe,0xad,0x7e]
+	seto 0x7eadbeef(%r10,%r9,8)
 
 // CHECK: 	monitorx
 // CHECK:  encoding: [0x0f,0x01,0xfa]
@@ -1550,9 +1550,9 @@ vmovq %xmm0, %rax
 // CHECK:  encoding: [0x47,0x89,0x3c,0x3f]
 movl %r15d, (%r15,%r15)
 
-// CHECK: nopq	3735928559(%rbx,%rcx,8)
-// CHECK:  encoding: [0x48,0x0f,0x1f,0x84,0xcb,0xef,0xbe,0xad,0xde]
-nopq	0xdeadbeef(%rbx,%rcx,8)
+// CHECK: nopq	2125315823(%rbx,%rcx,8)
+// CHECK:  encoding: [0x48,0x0f,0x1f,0x84,0xcb,0xef,0xbe,0xad,0x7e]
+nopq	0x7eadbeef(%rbx,%rcx,8)
 
 // CHECK: nopq	%rax
 // CHECK:  encoding: [0x48,0x0f,0x1f,0xc0]
@@ -1562,17 +1562,17 @@ nopq	%rax
 // CHECK: encoding: [0xf3,0x0f,0xc7,0xf8]
 rdpid %rax
 
-// CHECK: ptwritel 3735928559(%rbx,%rcx,8)
-// CHECK:  encoding: [0xf3,0x0f,0xae,0xa4,0xcb,0xef,0xbe,0xad,0xde]
-ptwritel 0xdeadbeef(%rbx,%rcx,8)
+// CHECK: ptwritel 2125315823(%rbx,%rcx,8)
+// CHECK:  encoding: [0xf3,0x0f,0xae,0xa4,0xcb,0xef,0xbe,0xad,0x7e]
+ptwritel 0x7eadbeef(%rbx,%rcx,8)
 
 // CHECK: ptwritel %eax
 // CHECK:  encoding: [0xf3,0x0f,0xae,0xe0]
 ptwritel %eax
 
-// CHECK: ptwriteq 3735928559(%rbx,%rcx,8)
-// CHECK:  encoding: [0xf3,0x48,0x0f,0xae,0xa4,0xcb,0xef,0xbe,0xad,0xde]
-ptwriteq 0xdeadbeef(%rbx,%rcx,8)
+// CHECK: ptwriteq 2125315823(%rbx,%rcx,8)
+// CHECK:  encoding: [0xf3,0x48,0x0f,0xae,0xa4,0xcb,0xef,0xbe,0xad,0x7e]
+ptwriteq 0x7eadbeef(%rbx,%rcx,8)
 
 // CHECK: ptwriteq %rax
 // CHECK:  encoding: [0xf3,0x48,0x0f,0xae,0xe0]
@@ -1586,9 +1586,9 @@ wbnoinvd
 // CHECK:  encoding: [0x0f,0x1c,0x40,0x04]
 cldemote 4(%rax)
 
-// CHECK: cldemote 3735928559(%rbx,%rcx,8)
-// CHECK:  encoding: [0x0f,0x1c,0x84,0xcb,0xef,0xbe,0xad,0xde]
-cldemote 0xdeadbeef(%rbx,%rcx,8)
+// CHECK: cldemote 2125315823(%rbx,%rcx,8)
+// CHECK:  encoding: [0x0f,0x1c,0x84,0xcb,0xef,0xbe,0xad,0x7e]
+cldemote 0x7eadbeef(%rbx,%rcx,8)
 
 // CHECK: umonitor %r13
 // CHECK:  encoding: [0xf3,0x41,0x0f,0xae,0xf5]
diff --git a/llvm/test/MC/X86/x86_64-asm-match.s b/llvm/test/MC/X86/x86_64-asm-match.s
index 50f25e59f49f45..7d35ebdbb2c200 100644
--- a/llvm/test/MC/X86/x86_64-asm-match.s
+++ b/llvm/test/MC/X86/x86_64-asm-match.s
@@ -31,9 +31,9 @@
 // CHECK:   Opcode result: complete match, selecting this opcode
 // CHECK: AsmMatcher: found 2 encodings with mnemonic 'crc32l'
 // CHECK: Trying to match opcode CRC32r32r32
-// CHECK:   Matching formal operand class MCK_GR32 against actual operand at index 1 (Memory: ModeSize=64,BaseReg=rbx,IndexReg=rcx,Scale=8,Disp=3735928559,SegReg=gs): Opcode result: multiple operand mismatches, ignoring this opcode
+// CHECK:   Matching formal operand class MCK_GR32 against actual operand at index 1 (Memory: ModeSize=64,BaseReg=rbx,IndexReg=rcx,Scale=8,Disp=2125315823,SegReg=gs): Opcode result: multiple operand mismatches, ignoring this opcode
 // CHECK: Trying to match opcode CRC32r32m32
-// CHECK:   Matching formal operand class MCK_Mem32 against actual operand at index 1 (Memory: ModeSize=64,BaseReg=rbx,IndexReg=rcx,Scale=8,Disp=3735928559,SegReg=gs): match success using generic matcher
+// CHECK:   Matching formal operand class MCK_Mem32 against actual operand at index 1 (Memory: ModeSize=64,BaseReg=rbx,IndexReg=rcx,Scale=8,Disp=2125315823,SegReg=gs): match success using generic matcher
 // CHECK:   Matching formal operand class MCK_GR32 against actual operand at index 2 (Reg:ecx): match success using generic matcher
 // CHECK:   Matching formal operand class InvalidMatchClass against actual operand at index 3: actual operand index out of range
 // CHECK:   Opcode result: complete match, selecting this opcode
@@ -62,7 +62,7 @@
 pshufb    CPI1_0(%rip), %xmm1
 sha1rnds4 $1, %xmm1, %xmm2
 pinsrw    $3, %ecx, %xmm5
-crc32l    %gs:0xdeadbeef(%rbx,%rcx,8),%ecx
+crc32l    %gs:0x7eadbeef(%rbx,%rcx,8),%ecx
 maskmovdqu     %xmm0, %xmm1
 vmaskmovdqu     %xmm0, %xmm1
 
diff --git a/llvm/test/MC/X86/x86_64-encoding.s b/llvm/test/MC/X86/x86_64-encoding.s
index ff541c2d6568dc..247b1dc656bc16 100644
--- a/llvm/test/MC/X86/x86_64-encoding.s
+++ b/llvm/test/MC/X86/x86_64-encoding.s
@@ -29,9 +29,9 @@ movq	%gs:(%rdi), %rax
 // CHECK:  encoding: [0xf2,0x0f,0x38,0xf1,0x43,0x04]
         crc32l	4(%rbx), %eax
 
-// CHECK: crc32l 	3735928559(%rbx,%rcx,8), %ecx
-// CHECK:  encoding: [0xf2,0x0f,0x38,0xf1,0x8c,0xcb,0xef,0xbe,0xad,0xde]
-        	crc32l   0xdeadbeef(%rbx,%rcx,8),%ecx
+// CHECK: crc32l 	2125315823(%rbx,%rcx,8), %ecx
+// CHECK:  encoding: [0xf2,0x0f,0x38,0xf1,0x8c,0xcb,0xef,0xbe,0xad,0x7e]
+        crc32l   0x7eadbeef(%rbx,%rcx,8),%ecx
 
 // CHECK: crc32l 	69, %ecx
 // CHECK:  encoding: [0xf2,0x0f,0x38,0xf1,0x0c,0x25,0x45,0x00,0x00,0x00]

>From 3ec07e60691c0f399b2f52df5dd693159a9a06e4 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 16 Dec 2023 20:10:27 -0800
Subject: [PATCH 2/2] improve warning

Pull Request: https://github.com/llvm/llvm-project/pull/75762
---
 llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 10 ++++++----
 llvm/test/MC/X86/displacement-overflow.s       | 10 ++++++----
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index ef622e08606cbf..1d40ce35c1b416 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -3079,12 +3079,14 @@ bool X86AsmParser::ParseMemOperand(unsigned SegReg, const MCExpr *Disp,
                                     " is not within [-2147483648, 2147483647]");
       } else if (!Is16) {
         if (!isUInt<32>(Imm < 0 ? -uint64_t(Imm) : uint64_t(Imm))) {
-          Warning(BaseLoc,
-                  "displacement " + Twine(Imm) + " shortened to signed 32-bit");
+          Warning(BaseLoc, "displacement " + Twine(Imm) +
+                               " shortened to 32-bit signed " +
+                               Twine(static_cast<int32_t>(Imm)));
         }
       } else if (!isUInt<16>(Imm < 0 ? -uint64_t(Imm) : uint64_t(Imm))) {
-        Warning(BaseLoc,
-                "displacement " + Twine(Imm) + " shortened to signed 16-bit");
+        Warning(BaseLoc, "displacement " + Twine(Imm) +
+                             " shortened to 16-bit signed " +
+                             Twine(static_cast<int16_t>(Imm)));
       }
     }
   }
diff --git a/llvm/test/MC/X86/displacement-overflow.s b/llvm/test/MC/X86/displacement-overflow.s
index 626003a29109ea..2882147af48280 100644
--- a/llvm/test/MC/X86/displacement-overflow.s
+++ b/llvm/test/MC/X86/displacement-overflow.s
@@ -15,11 +15,13 @@ leaq -0x80000001(%rip), %rax
 movl 0xffffffff(%eax), %eax
 leal -0xffffffff(%eax), %eax
 
-# CHECK: [[#@LINE+1]]:19: warning: displacement 4294967296 shortened to signed 32-bit
+# CHECK: [[#@LINE+1]]:19: warning: displacement 4294967296 shortened to 32-bit signed 0
 movl 0xffffffff+1(%eax), %eax
 
-# CHECK: [[#@LINE+1]]:20: warning: displacement -4294967296 shortened to signed 32-bit
+# CHECK: [[#@LINE+1]]:20: warning: displacement -4294967296 shortened to 32-bit signed 0
 leal -0xffffffff-1(%eax), %eax
+# CHECK: [[#@LINE+1]]:20: warning: displacement -4294967297 shortened to 32-bit signed -1
+leal -0xffffffff-2(%eax), %eax
 
 {disp8} leal 0x100(%ebx), %eax
 {disp8} leal -0x100(%ebx), %eax
@@ -29,8 +31,8 @@ leal -0xffffffff-1(%eax), %eax
 movw $0, 0xffff(%bp)
 movw $0, -0xffff(%si)
 
-# 32: [[#@LINE+1]]:19: warning: displacement 65536 shortened to signed 16-bit
+# 32: [[#@LINE+1]]:19: warning: displacement 65536 shortened to 16-bit signed 0
 movw $0, 0xffff+1(%bp)
-# 32: [[#@LINE+1]]:20: warning: displacement -65536 shortened to signed 16-bit
+# 32: [[#@LINE+1]]:20: warning: displacement -65536 shortened to 16-bit signed 0
 movw $0, -0xffff-1(%si)
 .endif



More information about the llvm-commits mailing list