From d7e11735fe4f22ba18c24178965d6fcd793c3a99 Mon Sep 17 00:00:00 2001 From: mio Date: Wed, 19 Jan 2022 23:01:44 +0100 Subject: [PATCH 1/4] Implement buffered stream Add close() and closed() to SimpleStreamBase Set seekable to false for SimpleStringBuffer --- qiling/extensions/pipe.py | 78 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/qiling/extensions/pipe.py b/qiling/extensions/pipe.py index 60729388e..bbf70562b 100644 --- a/qiling/extensions/pipe.py +++ b/qiling/extensions/pipe.py @@ -7,6 +7,7 @@ from qiling.os.posix import stat +import os class SimpleStringBuffer(TextIO): """Simple FIFO pipe. """ @@ -48,11 +49,21 @@ def writable(self) -> bool: def readable(self) -> bool: return True + def seekable(self) -> bool: + return False + class SimpleStreamBase: def __init__(self, fd: int, *args): super().__init__(*args) self.__fd = fd + self.__closed = False + + def close(self) -> None: + self.__closed = True + + def closed(self) -> bool: + return self.__closed def fileno(self) -> int: return self.__fd @@ -84,3 +95,70 @@ def flush(self) -> None: def writable(self) -> bool: return True + +class SimpleBufferedStream(TextIO): + """Simple buffered IO. + """ + + def __init__(self): + self.buff = bytearray() + self.cur = 0 + + def lseek(self, offset: int, origin: int) -> int: + if origin == 0: # SEEK_SET + base = 0 + elif origin == 1: # SEEK_CUR + base = self.cur + else: # SEEK_END + base = len(self.buff) - 1 + + if base + offset >= len(self.buff): + self.cur = base + offset - 1 + else: + self.cur = base + offset + + return self.cur + + def seek(self, offset: int, origin: int) -> int: + return self.lseek(offset, origin) + + def tell(self) -> int: + return self.cur + + def read(self, n: int = -1) -> bytes: + if n == -1: + ret = self.buff + else: + ret = self.buff[self.cur:self.cur + n] + + if self.cur + n >= len(self.buff) - 1: + self.cur = len(self.buff) + else: + self.cur = self.cur + n + + return bytes(ret) + + def readline(self, limit: int = -1) -> bytes: + ret = bytearray() + + while not (ret.endswith(b'\n') or len(ret) == limit): + ret.extend(self.read(1)) + + return bytes(ret) + + def write(self, s: bytes) -> int: + self.buff.extend(s) + + return len(s) + + def flush(self) -> None: + pass + + def writable(self) -> bool: + return True + + def readable(self) -> bool: + return True + + def seekable(self) -> bool: + return True \ No newline at end of file From bb7aeaecdf1b8e5369cbf91cf5f3f1bf055a9426 Mon Sep 17 00:00:00 2001 From: mio Date: Wed, 19 Jan 2022 23:14:33 +0100 Subject: [PATCH 2/4] Arrage imports --- qiling/extensions/pipe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiling/extensions/pipe.py b/qiling/extensions/pipe.py index bbf70562b..1602190f5 100644 --- a/qiling/extensions/pipe.py +++ b/qiling/extensions/pipe.py @@ -2,12 +2,12 @@ # # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # +import os from typing import TextIO from qiling.os.posix import stat -import os class SimpleStringBuffer(TextIO): """Simple FIFO pipe. """ From 04c3ebd3924409a72ed93da5ce27575fcd4563b3 Mon Sep 17 00:00:00 2001 From: lazymio Date: Sun, 23 Jan 2022 13:32:47 +0100 Subject: [PATCH 3/4] Fix buffered stream implementation Imitate os.lseek behaviour by raising OSError --- qiling/extensions/pipe.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/qiling/extensions/pipe.py b/qiling/extensions/pipe.py index 1602190f5..93c3bc9d7 100644 --- a/qiling/extensions/pipe.py +++ b/qiling/extensions/pipe.py @@ -2,8 +2,6 @@ # # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # -import os - from typing import TextIO from qiling.os.posix import stat @@ -49,6 +47,13 @@ def writable(self) -> bool: def readable(self) -> bool: return True + def seek(self, offset: int, origin: int) -> int: + # Imitate os.lseek + raise OSError("Illega Seek") + + def lseek(self, offset: int, origin: int) -> int: + return self.seek(offset, origin) + def seekable(self) -> bool: return False @@ -127,7 +132,8 @@ def tell(self) -> int: def read(self, n: int = -1) -> bytes: if n == -1: - ret = self.buff + ret = self.buff[self.cur:] + self.cur = len(self.buff) else: ret = self.buff[self.cur:self.cur + n] @@ -147,7 +153,12 @@ def readline(self, limit: int = -1) -> bytes: return bytes(ret) def write(self, s: bytes) -> int: - self.buff.extend(s) + if self.cur == 0: + self.buff.extend(s) + else: + self.buff[:self.cur].extend(s) + + self.cur += len(s) return len(s) @@ -161,4 +172,10 @@ def readable(self) -> bool: return True def seekable(self) -> bool: - return True \ No newline at end of file + return True + + # This method simply extends internal buffer with self.cur untouched. + def extend(self, s: bytes) -> int: + self.buff.extend(s) + + return len(s) \ No newline at end of file From f8df0c0c04cf2f901230bb20b93aff8dc8385231 Mon Sep 17 00:00:00 2001 From: lazymio Date: Sun, 23 Jan 2022 13:33:44 +0100 Subject: [PATCH 4/4] Format --- qiling/extensions/pipe.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qiling/extensions/pipe.py b/qiling/extensions/pipe.py index 93c3bc9d7..1fcbaeb8e 100644 --- a/qiling/extensions/pipe.py +++ b/qiling/extensions/pipe.py @@ -2,6 +2,7 @@ # # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # + from typing import TextIO from qiling.os.posix import stat