about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--example/jitter/run_with_linuxenv.py2
-rw-r--r--miasm/os_dep/linux/environment.py76
2 files changed, 68 insertions, 10 deletions
diff --git a/example/jitter/run_with_linuxenv.py b/example/jitter/run_with_linuxenv.py
index f981d2dd..9b17b172 100644
--- a/example/jitter/run_with_linuxenv.py
+++ b/example/jitter/run_with_linuxenv.py
@@ -78,7 +78,7 @@ elf_phdr_header = next(
 # Prepare the desired environment
 argv = [args.target.encode()] + [arg.encode() for arg in args.extra_args]
 if args.flags:
-    argv += ["-%s" % args.flags]
+    argv += [("-%s" % args.flags).encode()]
 envp = {b"PATH": b"/usr/local/bin", b"USER": linux_env.user_name}
 auxv = environment.AuxVec(
     elf_base_addr + elf_phdr_header.vaddr,
diff --git a/miasm/os_dep/linux/environment.py b/miasm/os_dep/linux/environment.py
index 8826abb7..42e45dd3 100644
--- a/miasm/os_dep/linux/environment.py
+++ b/miasm/os_dep/linux/environment.py
@@ -1,7 +1,9 @@
 from __future__ import print_function
 from collections import namedtuple
 import functools
+import logging
 import os
+import re
 import struct
 import termios
 
@@ -11,6 +13,8 @@ from miasm.core.interval import interval
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
 
 
+REGEXP_T = type(re.compile(''))
+
 StatInfo = namedtuple("StatInfo", [
     "st_dev", "st_ino", "st_nlink", "st_mode", "st_uid", "st_gid", "st_rdev",
     "st_size", "st_blksize", "st_blocks", "st_atime", "st_atimensec",
@@ -21,6 +25,11 @@ StatFSInfo = namedtuple("StatFSInfo", [
     "f_ffree", "f_fsid", "f_namelen", "f_frsize", "f_flags", "f_spare",
 ])
 
+log = logging.getLogger("environment")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log.addHandler(console_handler)
+log.setLevel(logging.WARNING)
 
 class FileDescriptor(object):
     """Stand for a file descriptor on a system
@@ -206,24 +215,73 @@ class FileSystem(object):
 
     def resolve_path(self, path, follow_link=True):
         """Resolve @path to the corresponding sandboxed path"""
+
+        # path_bytes is used for Python 2 / Python 3 compatibility
+        path_bytes = not isinstance(path, str)
+        path_sep = os.path.sep.encode() if path_bytes else os.path.sep
+
+        if path_bytes:
+            def _convert(subpath):
+                if not isinstance(subpath, str):
+                    return subpath
+                return subpath.encode()
+            def _convert_re(expr):
+                if isinstance(expr.pattern, str):
+                    try:
+                        return re.compile(
+                            expr.pattern.encode(),
+                            flags=expr.flags & ~re.UNICODE
+                        )
+                    except UnicodeEncodeError:
+                        # Will never match
+                        log.warning(
+                            'Cannot convert regexp to bytes %r %r',
+                            expr.pattern,
+                            expr.flags,
+                            exc_info=True,
+                        )
+                        return re.compile(b'$X')
+                return expr
+        else:
+            def _convert(subpath):
+                if not isinstance(subpath, str):
+                    return subpath.decode()
+                return subpath
+            def _convert_re(expr):
+                if not isinstance(expr.pattern, str):
+                    try:
+                        return re.compile(
+                            expr.pattern.decode(),
+                            flags=expr.flags & re.UNICODE
+                        )
+                    except UnicodeDecodeError:
+                        # Will never match
+                        log.warning(
+                            'Cannot convert regexp to str %r %r',
+                            expr.pattern,
+                            expr.flags,
+                            exc_info=True,
+                        )
+                        return re.compile('$X')
+                return expr
+
         # Remove '../', etc.
         path = os.path.normpath(path)
 
         # Passthrough
         for passthrough in self.passthrough:
-            if hasattr(passthrough, "match"):
-                if passthrough.match(path):
+            if isinstance(passthrough, REGEXP_T):
+                if _convert_re(passthrough).match(path):
                     return path
-            elif passthrough == path:
+            elif _convert(passthrough) == path:
                 return path
 
-        # Remove leading '/' if any (multiple '//' are handled by 'abspath'
-        if path.startswith(os.path.sep):
-            path = path[1:]
+        # Remove leading '/' if any
+        path = path.lstrip(path_sep)
 
-        base_path = os.path.abspath(self.base_path)
+        base_path = os.path.abspath(_convert(self.base_path))
         out_path = os.path.join(base_path, path)
-        assert out_path.startswith(base_path + os.path.sep)
+        assert out_path.startswith(base_path + path_sep)
         if os.path.islink(out_path):
             link_target = os.readlink(out_path)
             # Link can be absolute or relative -> absolute
@@ -463,7 +521,7 @@ class LinuxEnvironment(object):
         if not isinstance(fdesc, FileDescriptorDirectory):
             raise RuntimeError("Not implemented")
 
-        out = ""
+        out = b""
         # fdesc.listdir continues from where it stopped
         for name in fdesc.listdir():
             d_ino = 1 # Not the real one