mirror of
https://github.com/trailofbits/manticore.git
synced 2026-10-12 02:23:44 +00:00
* Organize examples in Makefile * .gitignore binaries created in examples/linux * Add a new Linux example using fclose * Add a test case for the fclose example binary See also #1602 and #1604. * Add a comment for the change from #1604 * Delete an obsolete comment * Add type hints to native integration tests * Do not squelch command output from test * Use `--worksapce` for `test_logger_verbosity` This should prevent extra mcore_* directories from hanging around after testing. * Reformat test_integration_native.py via `black`
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
arguments
|
||||
basic
|
||||
crackme
|
||||
crackme.c
|
||||
fclose
|
||||
helloworld
|
||||
ibranch
|
||||
indexhell
|
||||
nostdlib
|
||||
sendmail
|
||||
simple_copy
|
||||
simpleassert
|
||||
sindex
|
||||
strncmp
|
||||
+14
-1
@@ -3,7 +3,20 @@ CFLAGS=-O3 -static
|
||||
NOSTDLIBFLAGS=-fno-builtin -static -nostdlib -fomit-frame-pointer -fno-stack-protector
|
||||
PYTHON=python3
|
||||
|
||||
EXAMPLES=basic sindex strncmp arguments ibranch sendmail crackme indexhell helloworld simple_copy simpleassert
|
||||
EXAMPLES= \
|
||||
arguments \
|
||||
basic \
|
||||
crackme \
|
||||
fclose \
|
||||
helloworld \
|
||||
ibranch \
|
||||
indexhell \
|
||||
sendmail \
|
||||
simpleassert \
|
||||
simple_copy \
|
||||
sindex \
|
||||
strncmp \
|
||||
|
||||
OTHER_EXAMPLES=nostdlib
|
||||
|
||||
all: $(EXAMPLES) $(OTHER_EXAMPLES)
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// This example closes file descriptors 0, 1, and 2 (which correspond to stdin,
|
||||
// stdout, and stderr in most environments).
|
||||
//
|
||||
// This serves as a reduced testcase for what most of the programs in GNU
|
||||
// coreutils do. See #1602 and #1604 on GitHub.
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc >= 2 && strcmp(argv[1], "--close") == 0) {
|
||||
fprintf(stdout, "Closing file handles!\n");
|
||||
|
||||
int rc = 0;
|
||||
if (fclose(stdin) != 0) {
|
||||
rc += 1;
|
||||
}
|
||||
if (fclose(stdout) != 0) {
|
||||
rc += 2;
|
||||
}
|
||||
if (fclose(stderr) != 0) {
|
||||
rc += 4;
|
||||
}
|
||||
|
||||
return rc;
|
||||
} else {
|
||||
fprintf(stdout, "Not doing anything.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -665,12 +665,14 @@ class Linux(Platform):
|
||||
else:
|
||||
self.files.append(file_or_buffer)
|
||||
|
||||
# If file descriptors for stdin/stdout/stderr aren't closed, propagate them
|
||||
if self.files[0]:
|
||||
self.files[0].peer = self.output
|
||||
if self.files[1]:
|
||||
self.files[1].peer = self.output
|
||||
if self.files[2]:
|
||||
self.files[2].peer = self.output
|
||||
|
||||
self._getdents_c = state["_getdents_c"]
|
||||
self._closed_files = state["closed_files"]
|
||||
self.input.peer = self.files[0]
|
||||
|
||||
Executable
BIN
Binary file not shown.
@@ -10,26 +10,26 @@ import tempfile
|
||||
from manticore.binary import Elf, CGCElf
|
||||
from manticore.native.mappings import mmap, munmap
|
||||
|
||||
DIRPATH = os.path.dirname(__file__)
|
||||
from typing import List, Set
|
||||
|
||||
# TLDR: when we launch `python -m manticore` and one uses PyCharm remote interpreter
|
||||
# the `python` might not refer to proper interpreter. The `/proc/self/exe` is a workaround
|
||||
# so one doesn't have to set up virtualenv in a remote interpreter.
|
||||
PYTHON_BIN = sys.executable
|
||||
|
||||
DIRPATH: str = os.path.dirname(__file__)
|
||||
|
||||
PYTHON_BIN: str = sys.executable
|
||||
|
||||
|
||||
class NativeIntegrationTest(unittest.TestCase):
|
||||
_multiprocess_can_split_ = True
|
||||
|
||||
def setUp(self):
|
||||
def setUp(self) -> None:
|
||||
# Create a temporary directory
|
||||
self.test_dir = tempfile.mkdtemp()
|
||||
|
||||
def tearDown(self):
|
||||
def tearDown(self) -> None:
|
||||
# Remove the directory after the test
|
||||
shutil.rmtree(self.test_dir)
|
||||
|
||||
def _load_visited_set(self, visited):
|
||||
def _load_visited_set(self, visited: str) -> Set[int]:
|
||||
self.assertTrue(os.path.exists(visited))
|
||||
|
||||
with open(visited, "r") as f:
|
||||
@@ -37,7 +37,7 @@ class NativeIntegrationTest(unittest.TestCase):
|
||||
|
||||
return set(int(x[2:], 16) for x in vitems)
|
||||
|
||||
def _run_with_timeout(self, procargs, logfile, timeout=1200):
|
||||
def _run_with_timeout(self, procargs: List[str], logfile: str, timeout: int = 1200) -> None:
|
||||
|
||||
with open(os.path.join(os.pardir, logfile), "w") as output:
|
||||
po = subprocess.Popen(procargs, stdout=output)
|
||||
@@ -52,7 +52,7 @@ class NativeIntegrationTest(unittest.TestCase):
|
||||
self.assertTrue(secs_used < timeout)
|
||||
sys.stderr.write("\n")
|
||||
|
||||
def test_timeout(self):
|
||||
def test_timeout(self) -> None:
|
||||
filename = os.path.abspath(os.path.join(DIRPATH, "binaries", "arguments_linux_amd64"))
|
||||
self.assertTrue(filename.startswith(os.getcwd()))
|
||||
filename = filename[len(os.getcwd()) + 1 :]
|
||||
@@ -79,12 +79,15 @@ class NativeIntegrationTest(unittest.TestCase):
|
||||
|
||||
self.assertTrue(time.time() - t < 20)
|
||||
|
||||
def test_logger_verbosity(self):
|
||||
def test_logger_verbosity(self) -> None:
|
||||
"""
|
||||
Tests that default verbosity produces the expected volume of output
|
||||
"""
|
||||
filename = os.path.join(DIRPATH, "binaries", "basic_linux_amd64")
|
||||
output = subprocess.check_output([PYTHON_BIN, "-m", "manticore", "--no-color", filename])
|
||||
workspace = os.path.join(self.test_dir, "workspace")
|
||||
output = subprocess.check_output(
|
||||
[PYTHON_BIN, "-m", "manticore", "--no-color", "--workspace", workspace, filename]
|
||||
)
|
||||
|
||||
output_lines = output.splitlines()
|
||||
|
||||
@@ -96,8 +99,8 @@ class NativeIntegrationTest(unittest.TestCase):
|
||||
self.assertIn(b"Generated testcase No. 1 -", output_lines[2])
|
||||
|
||||
def _test_arguments_assertions_aux(
|
||||
self, binname, testcases_number, visited, add_assertion=False
|
||||
):
|
||||
self, binname: str, testcases_number: int, visited: List[int], add_assertion: bool = False
|
||||
) -> None:
|
||||
filename = os.path.abspath(os.path.join(DIRPATH, "binaries", binname))
|
||||
|
||||
self.assertTrue(filename.startswith(os.getcwd()))
|
||||
@@ -155,7 +158,7 @@ class NativeIntegrationTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual(len(set(visited)), len(visited)) # just a sanity check
|
||||
|
||||
def test_arguments_assertions_amd64(self):
|
||||
def test_arguments_assertions_amd64(self) -> None:
|
||||
self._test_arguments_assertions_aux(
|
||||
"arguments_linux_amd64",
|
||||
testcases_number=1,
|
||||
@@ -194,7 +197,7 @@ class NativeIntegrationTest(unittest.TestCase):
|
||||
add_assertion=True,
|
||||
)
|
||||
|
||||
def test_arguments_assertions_armv7(self):
|
||||
def test_arguments_assertions_armv7(self) -> None:
|
||||
self._test_arguments_assertions_aux(
|
||||
"arguments_linux_armv7",
|
||||
testcases_number=19,
|
||||
@@ -215,7 +218,7 @@ class NativeIntegrationTest(unittest.TestCase):
|
||||
],
|
||||
)
|
||||
|
||||
def test_decree(self):
|
||||
def test_decree(self) -> None:
|
||||
filename = os.path.abspath(os.path.join(DIRPATH, "binaries", "cadet_decree_x86"))
|
||||
self.assertTrue(filename.startswith(os.getcwd()))
|
||||
filename = filename[len(os.getcwd()) + 1 :]
|
||||
@@ -242,7 +245,7 @@ class NativeIntegrationTest(unittest.TestCase):
|
||||
actual = self._load_visited_set(os.path.join(DIRPATH, workspace, "visited.txt"))
|
||||
self.assertTrue(len(actual) > 100)
|
||||
|
||||
def test_basic_arm(self):
|
||||
def test_basic_arm(self) -> None:
|
||||
filename = os.path.abspath(os.path.join(DIRPATH, "binaries", "basic_linux_armv7"))
|
||||
workspace = os.path.join(self.test_dir, "workspace")
|
||||
cmd = [PYTHON_BIN, "-m", "manticore", "--no-color", "--workspace", workspace, filename]
|
||||
@@ -260,7 +263,25 @@ class NativeIntegrationTest(unittest.TestCase):
|
||||
with open(os.path.join(workspace, "test_00000001.stdout")) as f:
|
||||
self.assertIn("Message", f.read())
|
||||
|
||||
def test_brk_regression(self):
|
||||
def test_fclose_linux_amd64(self) -> None:
|
||||
"""
|
||||
Tests that the fclose example for amd64 linux doesn't crash; see #1602 and #1604.
|
||||
"""
|
||||
filename = os.path.abspath(os.path.join(DIRPATH, "binaries", "fclose_linux_amd64"))
|
||||
workspace = os.path.join(self.test_dir, "workspace")
|
||||
cmd = [
|
||||
PYTHON_BIN,
|
||||
"-m",
|
||||
"manticore",
|
||||
"--no-color",
|
||||
"--workspace",
|
||||
workspace,
|
||||
filename,
|
||||
"+++++++",
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
def test_brk_regression(self) -> None:
|
||||
"""
|
||||
Tests for brk behavior. Source of brk_static_amd64:
|
||||
|
||||
@@ -299,7 +320,7 @@ class NativeIntegrationTest(unittest.TestCase):
|
||||
# with open(os.path.join(workspace, "test_00000000.messages")) as f:
|
||||
# self.assertIn("finished with exit status: 0", f.read())
|
||||
|
||||
def test_unaligned_mappings(self):
|
||||
def test_unaligned_mappings(self) -> None:
|
||||
# This test ensures that mapping file contents at non page-aligned offsets is possible.
|
||||
filename = os.path.join(os.path.dirname(__file__), "binaries", "basic_linux_amd64")
|
||||
with open(filename, "rb") as f:
|
||||
|
||||
Reference in New Issue
Block a user