Repository: angr/angr

Issue:
SHR does not set OF correctly
### Description

Overflow flag on "shr" does not behave to specifications and observed behaviour on real CPU.


### Steps to reproduce the bug

    # The OF flag is affected only on 1-bit shifts.  [..] 
    # For the SHR instruction, the OF flag is set to the most-significant bit of the original operand. 
    p = angr.load_shellcode(asm("shr rax,1"), 'x86_64')
    start_state.registers.store('rax', (1<<64)-1)
    end_state = start_state.step(num_inst=1).all_successors[0]
    print("overflow (0x800) should be set: %s" % end_state.regs.flags)

    # The OF flag is affected only for 1-bit shifts [..] otherwise, it is undefined
    p = angr.load_shellcode(asm("shr rax,2"), 'x86_64') 
    start_state = p.factory.blank_state()
    start_state.registers.store('rax', (1<<64)-1)
    end_state = start_state.step(num_inst=1).all_successors[0]
    print("overflow (0x800) should now be undefined: %s" % end_state.regs.flags)

### Environment

angr environment report
=============================
Date: 2023-03-29 16:00:52.987833
!!! running in global environment.  Are you sure? !!!
Platform: linux-x86_64
Python version: 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0]
######## angr #########
Python found it in /home/user/.local/lib/python3.10/site-packages/angr
Pip version angr 9.2.42
Couldn't find git info
######## ailment #########
Python found it in /home/user/.local/lib/python3.10/site-packages/ailment
Pip version ailment 9.2.42
Couldn't find git info
######## cle #########
Python found it in /home/user/.local/lib/python3.10/site-packages/cle
Pip version cle 9.2.42
Couldn't find git info
######## pyvex #########
Python found it in /home/user/.local/lib/python3.10/site-packages/pyvex
Pip version pyvex 9.2.42
Couldn't find git info
######## claripy #########
Python found it in /home/user/.local/lib/python3.10/site-packages/claripy
Pip version claripy 9.2.42
Couldn't find git info
######## archinfo #########
Python found it in /home/user/.local/lib/python3.10/site-packages/archinfo
Pip version archinfo 9.2.42
Couldn't find git info
######## z3 #########
Python found it in /home/user/.local/lib/python3.10/site-packages/z3
Pip version z3-solver 4.10.2.0
Couldn't find git info
######## unicorn #########
Python found it in /home/user/.local/lib/python3.10/site-packages/unicorn
Pip version unicorn 2.0.1.post1
Couldn't find git info
######### Native Module Info ##########
angr: <CDLL '/home/user/.local/lib/python3.10/site-packages/angr/state_plugins/../lib/angr_native.so', handle 55644eca1840 at 0x7fb09de46830>
unicorn: <CDLL '/home/user/.local/lib/python3.10/site-packages/unicorn/lib/libunicorn.so.2', handle 55644e636920 at 0x7fb0a310ea10>
pyvex: <cffi.api._make_ffi_library.<locals>.FFILibrary object at 0x7fb0a41ea260>
z3: <CDLL '/home/user/.local/lib/python3.10/site-packages/z3/lib/libz3.so', handle 55644e9a32d0 at 0x7fb0a3019600>


### Additional context

_No response_


Discussion:

Resolving patch:
diff --git a/angr/engines/vex/claripy/ccall.py b/angr/engines/vex/claripy/ccall.py
--- a/angr/engines/vex/claripy/ccall.py
+++ b/angr/engines/vex/claripy/ccall.py
@@ -500,7 +500,7 @@ def pc_actions_SHR(state, nbits, remaining, shifted, cc_ndep, platform=None):
     af = claripy.BVV(0, 1)
     zf = calc_zerobit(remaining)
     sf = remaining[nbits - 1]
-    of = (remaining[0] ^ shifted[0])[0]
+    of = (remaining[nbits - 1] ^ shifted[nbits - 1])[0]
     return pc_make_rdata(data[platform]["size"], cf, pf, af, zf, sf, of, platform=platform)
 
 


Test patch:
diff --git a/tests/test_vex.py b/tests/test_vex.py
--- a/tests/test_vex.py
+++ b/tests/test_vex.py
@@ -131,6 +131,18 @@ def test_ccall():
     assert s.solver.is_true(sf == 0)
     assert s.solver.is_true(of == 0)
 
+    l.debug("Testing pc_actions_SHR")
+    l.debug("(64-bit) SHR 0xffffffffffffffff 1")
+    result = s.solver.BVV(0x7FFFFFFFFFFFFFFF, 64)
+    subshifted_result = s.solver.BVV(0xFFFFFFFFFFFFFFFF, 64)
+    cf, pf, af, zf, sf, of = s_ccall.pc_actions_SHR(s, 64, result, subshifted_result, None, platform="AMD64")
+    assert s.solver.is_true(cf == 1)
+    assert s.solver.is_true(pf == 1)
+    assert s.solver.is_true(af == 0)
+    assert s.solver.is_true(zf == 0)
+    assert s.solver.is_true(sf == 0)
+    assert s.solver.is_true(of == 1)
+
     l.debug("Testing amd64_actions_ADCX")
 
     l.debug("(ADCX, 32-bit) 0xffffffff + 1...")