Skip to content

Commit

Permalink
Introduced 'as_signed' utility method for turning unsigned values int…
Browse files Browse the repository at this point in the history
…o signed ones
  • Loading branch information
elicn committed Jul 2, 2024
1 parent fef6134 commit 1c90e4a
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 17 deletions.
2 changes: 1 addition & 1 deletion qiling/os/posix/syscall/mman.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ class mmap_flags(IntFlag):
label = '[mmap anonymous]'

else:
fd = ql.unpacks(ql.pack(fd))
fd = ql.os.utils.as_signed(fd, 32)

if fd not in range(NR_OPEN):
return -EBADF
Expand Down
5 changes: 2 additions & 3 deletions qiling/os/posix/syscall/unistd.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ def ql_syscall_faccessat(ql: Qiling, dirfd: int, filename: int, mode: int):


def ql_syscall_lseek(ql: Qiling, fd: int, offset: int, origin: int):
offset = ql.unpacks(ql.pack(offset))
offset = ql.os.utils.as_signed(offset, 32)

f = get_opened_fd(ql.os, fd)

Expand All @@ -285,8 +285,7 @@ def ql_syscall_lseek(ql: Qiling, fd: int, offset: int, origin: int):


def ql_syscall__llseek(ql: Qiling, fd: int, offset_high: int, offset_low: int, result: int, whence: int):
# treat offset as a signed value
offset = ql.unpack64s(ql.pack64((offset_high << 32) | offset_low))
offset = ql.os.utils.as_signed((offset_high << 32) | offset_low, 64)

f = get_opened_fd(ql.os, fd)

Expand Down
18 changes: 7 additions & 11 deletions qiling/os/posix/syscall/wait.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,15 @@
from qiling.os.posix.const import ECHILD

def ql_syscall_wait4(ql: Qiling, pid: int, wstatus: int, options: int, rusage: int):
# convert to signed (pid_t is 32bit)
pid = ql.unpack32s(ql.pack32(pid))
# python expects options to be a signed 32bit int
options = ql.unpack32s(ql.pack32(options))
pid = ql.os.utils.as_signed(pid, 32)
options = ql.os.utils.as_signed(options, 32)

try:
spid, status, _ = os.wait4(pid, options)

if wstatus:
ql.mem.write_ptr(wstatus, status, 4)

retval = spid
except ChildProcessError:
retval = -ECHILD
return -ECHILD

if wstatus:
ql.mem.write_ptr(wstatus, status, 4)

return retval
return spid
21 changes: 20 additions & 1 deletion qiling/os/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,25 @@ class QlOsUtils:
def __init__(self, ql: Qiling):
self.ql = ql

@staticmethod
def as_signed(value: int, nbits: int) -> int:
"""Transform an unsigned integer value into its 2's complement signed value
equivalent. This method has no effect on signed integers.
Args:
value: an unsigned integer to transform
nbits: value bit size
Returns: a signed integer
"""

# truncate value to specified bit size
value &= (1 << nbits) - 1

msb = 1 << (nbits - 1)

return -(value & ~(msb - 1)) | value

def read_string(self, address: int, encoding: str, maxlen: int = 0) -> str:
"""Read a null-terminated string from memory.
Expand Down Expand Up @@ -244,4 +263,4 @@ def __update_ellipsis(self, args: Iterable[int]) -> Callable[[MutableMapping], N
def __do_update(params: MutableMapping) -> None:
params.update((f'{QlOsUtils.ELLIPSIS_PREF}{i}', a) for i, a in enumerate(args))

return __do_update
return __do_update
2 changes: 1 addition & 1 deletion qiling/os/windows/dlls/kernel32/fileapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ def _CreateFileMapping(ql: Qiling, address: int, params):

req_size = (dwMaximumSizeHigh << 32) | dwMaximumSizeLow

if hFile == ql.unpack(ql.packs(INVALID_HANDLE_VALUE)):
if hFile == ql.os.utils.as_signed(INVALID_HANDLE_VALUE, ql.arch.bits):
fmobj = FileMappingMem()

else:
Expand Down

0 comments on commit 1c90e4a

Please sign in to comment.