Skip to content

Commit

Permalink
Merge pull request #4 from trailofbits/master
Browse files Browse the repository at this point in the history
Make CodeCov wait for reports from all CI jobs (trailofbits#1661)
  • Loading branch information
fengjixuchui authored Apr 24, 2020
2 parents f044872 + 1e82ec4 commit e82b9f3
Show file tree
Hide file tree
Showing 57 changed files with 1,286 additions and 824 deletions.
19 changes: 12 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Set up Python 3.6
uses: actions/setup-python@v1
with:
Expand Down Expand Up @@ -66,13 +66,13 @@ jobs:
# concolic assumes presence of ../linux/simpleassert
echo "Running concolic.py..."
HW=../linux/helloworld
python ./concolic.py
coverage run ./concolic.py
if [ $? -ne 0 ]; then
return 1
fi
echo "Running count_instructions.py..."
python ./count_instructions.py $HW |grep -q Executed
coverage run ./count_instructions.py $HW |grep -q Executed
if [ $? -ne 0 ]; then
return 1
fi
Expand All @@ -81,21 +81,21 @@ jobs:
gcc -static -g src/state_explore.c -o state_explore
ADDRESS=0x$(objdump -S state_explore | grep -A 1 '((value & 0xff) != 0)' |
tail -n 1 | sed 's|^\s*||g' | cut -f1 -d:)
python ./introduce_symbolic_bytes.py state_explore $ADDRESS
coverage run ./introduce_symbolic_bytes.py state_explore $ADDRESS
if [ $? -ne 0 ]; then
return 1
fi
echo "Running run_simple.py..."
gcc -x c -static -o hello test_run_simple.c
python ./run_simple.py hello
coverage run ./run_simple.py hello
if [ $? -ne 0 ]; then
return 1
fi
echo "Running run_hook.py..."
MAIN_ADDR=$(nm $HW|grep 'T main' | awk '{print "0x"$1}')
python ./run_hook.py $HW $MAIN_ADDR
coverage run ./run_hook.py $HW $MAIN_ADDR
if [ $? -ne 0 ]; then
return 1
fi
Expand All @@ -105,7 +105,7 @@ jobs:
gcc -static -g src/state_explore.c -o state_explore
SE_ADDR=0x$(objdump -S state_explore | grep -A 1 'value == 0x41' |
tail -n 1 | sed 's|^\s*||g' | cut -f1 -d:)
python ./state_control.py state_explore $SE_ADDR
coverage run ./state_control.py state_explore $SE_ADDR
if [ $? -ne 0 ]; then
return 1
fi
Expand Down Expand Up @@ -193,7 +193,9 @@ jobs:
launch_examples
RESULT=$?
echo Ran example scripts
coverage xml
popd
cp examples/script/coverage.xml .
return $RESULT
}
Expand Down Expand Up @@ -240,3 +242,6 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.xml
yml: ./codecov.yml
# Disabled this line because Codecov has been extra flaky lately, and having to re-run the entire
# test suite until every coverage upload step succeeds is more of a hassle than it's worth.
# fail_ci_if_error: true
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@

[![Build Status](https://img.shields.io/github/workflow/status/trailofbits/manticore/CI/master)](https://github.com/trailofbits/manticore/actions?query=workflow%3ACI)
[![Codecov](https://img.shields.io/codecov/c/github/trailofbits/manticore)](https://codecov.io/github/trailofbits/manticore)
[![PyPI version](https://badge.fury.io/py/manticore.svg)](https://badge.fury.io/py/manticore)
[![PyPI Version](https://badge.fury.io/py/manticore.svg)](https://badge.fury.io/py/manticore)
[![Slack Status](https://empireslacking.herokuapp.com/badge.svg)](https://empireslacking.herokuapp.com)
[![Documentation Status](https://readthedocs.org/projects/manticore/badge/?version=latest)](http://manticore.readthedocs.io/en/latest/?badge=latest)
[![Example Status](https://img.shields.io/github/workflow/status/trailofbits/manticore-examples/CI/master)](https://github.com/trailofbits/manticore-examples/actions?query=workflow%3ACI)
[![LGTM Total Alerts](https://img.shields.io/lgtm/alerts/g/trailofbits/manticore.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/trailofbits/manticore/alerts/)

Manticore is a symbolic execution tool for analysis of smart contracts and binaries.

Expand Down
7 changes: 7 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
comment: false

codecov:
notify:
# We have 8 test steps that produce coverage data.
# If we add or remove any, we need to change this number.
after_n_builds: 8
wait_for_ci: yes
1 change: 1 addition & 0 deletions examples/linux/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ basic
crackme
crackme.c
fclose
fileio
helloworld
ibranch
indexhell
Expand Down
1 change: 1 addition & 0 deletions examples/linux/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ EXAMPLES= \
basic \
crackme \
fclose \
fileio \
helloworld \
ibranch \
indexhell \
Expand Down
35 changes: 35 additions & 0 deletions examples/linux/fileio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// This example demonstrates reading & writing from files.

#include <errno.h>
#include <stdio.h>
#include <string.h>

int main(int argc, const char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s FILE\n", argv[0]);
return 0;
}

const char *fname = argv[1];
FILE *infile = fopen(fname, "r");
if (!infile) {
fprintf(stderr, "Error opening %s: %s\n", fname, strerror(errno));
return 2;
}

char *line;
size_t line_size;
ssize_t nread = getline(&line, &line_size, infile);
if (nread == -1) {
fprintf(stderr, "Error reading from %s: %s\n", fname, strerror(errno));
return 3;
}

if (strcmp("my voice is my passport verify me", line) == 0) {
fprintf(stdout, "Welcome!\n");
return 0;
} else {
fprintf(stdout, "Access denied.\n");
return 4;
}
}
6 changes: 6 additions & 0 deletions lgtm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
queries:
- exclude: py/clear-text-logging-sensitive-data

path_classifiers:
examples:
- examples/
5 changes: 4 additions & 1 deletion manticore/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .core.manticore import ManticoreBase, set_verbosity
from .ethereum.cli import ethereum_main
from .wasm.cli import wasm_main
from .utils import config, log, install_helper
from .utils import config, log, install_helper, resources

consts = config.get_group("main")
consts.add("recursionlimit", default=10000, description="Value to set for Python recursion limit")
Expand All @@ -38,6 +38,9 @@ def main():

set_verbosity(args.v)

resources.check_disk_usage()
resources.check_memory_usage()

if args.argv[0].endswith(".sol") or is_supported(args.argv[0]):
ethereum_main(args, logger)
elif args.argv[0].endswith(".wasm") or args.argv[0].endswith(".wat"):
Expand Down
23 changes: 10 additions & 13 deletions manticore/core/manticore.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,9 @@ def newFunction(self, *args, **kw):
"terminate_execution",
}

def __init__(self, initial_state, workspace_url=None, policy="random", **kwargs):
def __init__(self, initial_state, workspace_url=None, outputspace_url=None, **kwargs):
"""
:param initial_state: State to start from.
Manticore symbolically explores program states.
Manticore symbolically explores program states.
**Manticore phases**
Expand Down Expand Up @@ -251,10 +249,9 @@ def __init__(self, initial_state, workspace_url=None, policy="random", **kwargs)
further user action. This is a final list.
:param initial_state: the initial root `State` object
:type state: State
:param initial_state: the initial root `State` object to start from
:param workspace_url: workspace folder name
:param policy: scheduling policy
:param outputspace_url: Folder to place final output. Defaults to workspace
:param kwargs: other kwargs, e.g.
"""
super().__init__()
Expand Down Expand Up @@ -288,9 +285,9 @@ def __init__(self, initial_state, workspace_url=None, policy="random", **kwargs)
raise TypeError(f"Invalid workspace type: {type(workspace_url).__name__}")
self._workspace = Workspace(workspace_url)
# reuse the same workspace if not specified
if workspace_url is None:
workspace_url = f"fs:{self._workspace.uri}"
self._output = ManticoreOutput(workspace_url)
if outputspace_url is None:
outputspace_url = f"fs:{self._workspace.uri}"
self._output = ManticoreOutput(outputspace_url)

# The set of registered plugins
# The callback methods defined in the plugin object will be called when
Expand Down Expand Up @@ -346,7 +343,7 @@ def _fork(self, state, expression, policy="ALL", setstate=None):
The optional setstate() function is supposed to set the concrete value
in the child state.
Parent state is removed from the busy list and tht child states are added
Parent state is removed from the busy list and the child states are added
to the ready list.
"""
Expand Down Expand Up @@ -713,7 +710,7 @@ def count_terminated_states(self):
""" Terminated states count """
return len(self._terminated_states)

def generate_testcase(self, state, message="test", name="test"):
def generate_testcase(self, state, message: str = "test", name: str = "test"):
if message == "test" and hasattr(state, "_terminated_by") and state._terminated_by:
message = str(state._terminated_by)
testcase = self._output.testcase(prefix=name)
Expand All @@ -728,7 +725,7 @@ def generate_testcase(self, state, message="test", name="test"):
return testcase

@at_not_running
def register_plugin(self, plugin):
def register_plugin(self, plugin: Plugin):
# Global enumeration of valid events
assert isinstance(plugin, Plugin)
assert plugin not in self.plugins, "Plugin instance already registered"
Expand Down
1 change: 0 additions & 1 deletion manticore/core/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ def will_write_memory_callback(self, state, where, value, size):
def did_write_memory_callback(self, state, where, value, size):
if self.current_pc == where:
raise Exception
return

entry = {"type": "mem_write", "where": where, "value": value, "size": size}
state.context.setdefault(self.context_key, []).append(entry)
Expand Down
22 changes: 7 additions & 15 deletions manticore/core/smtlib/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,28 @@ def __reduce__(self):
},
)

def __enter__(self):
def __enter__(self) -> "ConstraintSet":
assert self._child is None
self._child = self.__class__()
self._child._parent = self
self._child._sid = self._sid
self._child._declarations = dict(self._declarations)
return self._child

def __exit__(self, ty, value, traceback):
def __exit__(self, ty, value, traceback) -> None:
self._child._parent = None
self._child = None

def __len__(self):
def __len__(self) -> int:
if self._parent is not None:
return len(self._constraints) + len(self._parent)
return len(self._constraints)

def add(self, constraint, check=False):
def add(self, constraint) -> None:
"""
Add a constraint to the set
:param constraint: The constraint to add to the set.
:param check: Currently unused.
:return:
"""
if isinstance(constraint, bool):
constraint = BoolConstant(constraint)
Expand All @@ -101,13 +99,7 @@ def add(self, constraint, check=False):

self._constraints.append(constraint)

if check:
from ...core.smtlib import solver

if not solver.check(self):
raise ValueError("Added an impossible constraint")

def _get_sid(self):
def _get_sid(self) -> int:
""" Returns a unique id. """
assert self._child is None
self._sid += 1
Expand Down Expand Up @@ -263,7 +255,7 @@ def _make_unique_name(self, name="VAR"):
name = f"{name}_{self._get_sid()}"
return name

def is_declared(self, expression_var):
def is_declared(self, expression_var) -> bool:
""" True if expression_var is declared in this constraint set """
if not isinstance(expression_var, Variable):
raise ValueError(f"Expression must be a Variable (not a {type(expression_var)})")
Expand Down Expand Up @@ -326,7 +318,7 @@ def migrate(self, expression, name_migration_map=None):
name=migrated_name,
).array
else:
raise NotImplemented(
raise NotImplementedError(
f"Unknown expression type {type(foreign_var)} encountered during expression migration"
)
# Update the var to var mapping
Expand Down
2 changes: 1 addition & 1 deletion manticore/core/smtlib/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class Bool(Expression):
def __init__(self, *operands, **kwargs):
super().__init__(*operands, **kwargs)

def cast(self, value: Union[int, bool], **kwargs) -> Union["BoolConstant", "Bool"]:
def cast(self, value: Union["Bool", int, bool], **kwargs) -> Union["BoolConstant", "Bool"]:
if isinstance(value, Bool):
return value
return BoolConstant(bool(value), **kwargs)
Expand Down
Loading

0 comments on commit e82b9f3

Please sign in to comment.