qilingframework / qiling

A True Instrumentable Binary Emulation Framework
https://qiling.io
GNU General Public License v2.0
5.06k stars 737 forks source link

POSIX ql_syscall_readv returns incorrect value. #1443

Closed iMoD1998 closed 2 months ago

iMoD1998 commented 7 months ago

*Describe the bug readv() according to the manpages should return the number of bytes read but it seems to return the size of the iovec everytime???

Sample Code

def ql_syscall_readv(ql: Qiling, fd: int, vec: int, vlen: int):
    regreturn = 0
    size_t_len = ql.arch.pointersize
    iov = ql.mem.read(vec, vlen * size_t_len * 2)
    ql.log.debug('readv() CONTENT:')

    for i in range(vlen):
        addr = ql.unpack(iov[i * size_t_len * 2 : i * size_t_len * 2 + size_t_len])
        l = ql.unpack(iov[i * size_t_len * 2 + size_t_len : i * size_t_len * 2 + size_t_len * 2])
        regreturn += l

        if hasattr(ql.os.fd[fd], 'read'):
            data = ql.os.fd[fd].read(l)
            ql.log.debug(f'{data!r}')
            ql.mem.write(addr, data)

    return regreturn

Expected behavior readv() should return the amount of bytes read from fd.

Proposed Change My solution that fixes this looks like the following:

def ql_syscall_readv(ql: Qiling, fd: int, vec: int, vlen: int):
    regreturn = 0
    size_t_len = ql.arch.pointersize
    iov = ql.mem.read(vec, vlen * size_t_len * 2)
    ql.log.debug('readv() CONTENT:')

    for i in range(vlen):
        addr = ql.unpack(iov[i * size_t_len * 2 : i * size_t_len * 2 + size_t_len])
        l = ql.unpack(iov[i * size_t_len * 2 + size_t_len : i * size_t_len * 2 + size_t_len * 2])

        if hasattr(ql.os.fd[fd], 'read'):
            data = ql.os.fd[fd].read(l)
            ql.log.debug(f'{data!r}')
            ql.mem.write(addr, data)
            regreturn += len(data)

    return regreturn