Skip to content

Commit 3d41ed4

Browse files
authored
Merge branch 'master' into nirizr/zestreleaser
2 parents a6a34e4 + 34296fd commit 3d41ed4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+786
-419
lines changed

.travis.yml

+29-16
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,36 @@ matrix:
44
include:
55
- python: "2.7"
66
env: PROJECT=idaplugin ENV=conda
7+
- python: "3.6"
8+
env: PROJECT=idaplugin ENV=conda
79
- python: "2.7"
810
env: PROJECT=server ENV=data DJANGO_SETTINGS_MODULE='rematch.settings.debug'
911
services:
10-
- mysql
1112
- rabbitmq
12-
- python: "3.5"
13+
- python: "3.6"
1314
env: PROJECT=server ENV=data DJANGO_SETTINGS_MODULE='rematch.settings.production'
1415
services:
15-
- mysql
1616
- rabbitmq
1717
- python: "2.7"
1818
env: PROJECT=server ENV=docker DJANGO_SETTINGS_MODULE='rematch.settings.docker'
19-
services: docker
19+
services:
20+
- docker
2021
- python: "2.7"
2122
env: PROJECT=setup.py
2223
- python: "3.6"
2324
env: PROJECT=setup.py
2425
- python: "3.6"
2526
env: PROJECT=docs
27+
- python: 2.7
28+
env: PROJECT=interop ENV=conda DJANGO_SETTINGS_MODULE='rematch.settings.debug'
2629

2730
branches:
2831
only:
2932
- master
3033

34+
addons:
35+
mariadb: '10.3'
36+
3137
# Handle git submodules ourselves to replace ssh login with https login
3238
git:
3339
submodules: false
@@ -44,36 +50,43 @@ install:
4450
docker-compose -f ./${PROJECT}/docker-compose.yml build ;
4551
docker-compose -f ./${PROJECT}/docker-compose.yml up -d ;
4652
if [ -f ./tests/${PROJECT}/requirements.txt ]; then
47-
docker-compose -f ./${PROJECT}/docker-compose.yml exec web pip install -r ./tests/requirements.txt ;
53+
docker-compose -f ./${PROJECT}/docker-compose.yml exec web pip install --upgrade -r ./tests/server/requirements.txt ;
4854
fi ;
49-
docker-compose -f ./${PROJECT}/docker-compose.yml exec web pip install coveralls pytest-cov ;
55+
docker-compose -f ./${PROJECT}/docker-compose.yml exec web pip install --upgrade coveralls pytest-cov ;
56+
pip install --upgrade flake8 ;
5057
fi ;
5158
- if [ "${ENV}" = "conda" ]; then
52-
wget https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh -O miniconda.sh ;
59+
wget "https://repo.continuum.io/miniconda/Miniconda${TRAVIS_PYTHON_VERSION:0:1}-latest-Linux-x86_64.sh" -O miniconda.sh ;
5360
bash ./miniconda.sh -b -p "${HOME}/miniconda" ;
5461
export PATH=${HOME}/miniconda/bin:$PATH ;
5562
conda info -a ;
5663
conda install --yes python=${TRAVIS_PYTHON_VERSION} pyqt ;
5764
fi ;
5865
- if [ "${ENV}" = "data" ]; then
59-
pip install --only-binary=numpy,scipy numpy scipy ;
60-
fi ;
61-
- if [ -f tests/${PROJECT}/requirements.txt ]; then
62-
pip install -r tests/${PROJECT}/requirements.txt ;
66+
pip install --upgrade --only-binary=numpy,scipy numpy scipy ;
6367
fi ;
64-
- if [ -f "${PROJECT}/requirements.txt" ]; then
65-
pip install -r "${PROJECT}/requirements.txt" ;
68+
- if [ "${ENV}" != "docker" ]; then
69+
if [ -f "tests/${PROJECT}/requirements.txt" ]; then
70+
pip install --upgrade -r "tests/${PROJECT}/requirements.txt" ;
71+
fi ;
72+
if [ -f "${PROJECT}/requirements.txt" ]; then
73+
pip install --upgrade -r "${PROJECT}/requirements.txt" ;
74+
fi ;
75+
pip install --upgrade flake8 coveralls pytest-cov ;
6676
fi ;
67-
- pip install flake8 coveralls pytest-cov ;
6877

6978
script:
7079
- flake8 ./${PROJECT} --show-source --statistics
7180
- if [ -d ./tests/${PROJECT} ]; then flake8 ./tests/${PROJECT} --show-source ; fi ;
7281
- if [ -d ./tests/${PROJECT} ]; then
7382
if [ "${ENV}" = "docker" ]; then
74-
docker-compose -f ./${PROJECT}/docker-compose.yml exec web py.test -rapP ./ --verbose --cov-report= --cov=. ;
83+
docker-compose -f ./${PROJECT}/docker-compose.yml exec web /bin/bash -c "PYTHONPATH=. py.test -rapP ./${PROJECT} ./tests/${PROJECT} -p tests.server.pymysql_mysqldb --verbose --cov-report= --cov=${PROJECT} ;" ;
84+
elif [ "${PROJECT}" = "interop" ]; then
85+
PYTHONPATH=. py.test -rapP ./server ./idaplugin ./tests/${PROJECT} -p tests.server.pymysql_mysqldb --verbose --cov-report= --cov=server --cov=idaplugin ;
86+
elif [ "${PROJECT}" = "server" ]; then
87+
PYTHONPATH=. py.test -rapP ./${PROJECT} ./tests/${PROJECT} -p tests.server.pymysql_mysqldb --verbose --cov-report= --cov=${PROJECT} ;
7588
else
76-
PYTHONPATH=. py.test -rapP ./${PROJECT} ./tests/${PROJECT} --verbose --cov-report= --cov=${PROJECT} ;
89+
py.test -rapP ./${PROJECT} ./tests/${PROJECT} --verbose --cov-report= --cov=${PROJECT} ;
7790
fi ;
7891
fi ;
7992
- if [ "${PROJECT}" = "setup.py" ]; then python ./setup.py server install ; fi ;

README.rst

+11-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,17 @@ the webservice's docker image by executing the following command:
3535

3636
.. code-block:: console
3737
38-
$ docker-compose -f ./server/docker-compose.yml build ;
39-
$ docker-compose -f ./server/docker-compose.yml up -d ;
38+
$ docker-compose -f ./server/docker-compose.yml build ;
39+
$ docker-compose -f ./server/docker-compose.yml up -d ;
40+
41+
To create the rematch server administrator execute the following command:
42+
43+
.. code-block:: console
44+
45+
$ docker-compose -f ./server/docker-compose.yml exec web ./server/manage.py createsuperuser
46+
47+
Finally, point your browser to http://SERVER_IP:8000/admin/ to manage the
48+
service and add more users.
4049

4150
.. |Read The Docs| image:: https://readthedocs.org/projects/rematch/badge/?version=latest
4251
:alt: Read The Docs

docs/installation.rst

+10
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ directory of the rematch repository:
4141
$ docker-compose -f ./server/docker-compose.yml build ;
4242
$ docker-compose -f ./server/docker-compose.yml up -d ;
4343
44+
Then execute the following command to set up the rematch server adminstrator
45+
account:
46+
47+
.. code-block:: console
48+
49+
$ docker-compose -f ./server/docker-compose.yml exec web ./server/manage.py createsuperuser
50+
51+
Finally, point your browser to http://SERVER_IP:8000/admin/ to manage the
52+
service and add more users.
53+
4454
Installing Rematch IDA Plugin
4555
-----------------------------
4656

idaplugin/plugin_rematch.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import rematch
1+
from . import rematch
22

33

44
def PLUGIN_ENTRY(): # noqa: N802

idaplugin/rematch/actions/__init__.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import base
2-
import login
3-
import match
4-
import project
5-
import settings
1+
from . import base
2+
from . import login
3+
from . import match
4+
from . import project
5+
from . import settings
66

77

88
__all__ = [base, login, match, project, settings]

idaplugin/rematch/actions/base.py

+7-22
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ def __init__(self, ui_class):
1616
super(Action, self).__init__()
1717
self.ui_class = ui_class
1818
self.ui = None
19+
self._running = False
1920

2021
def __repr__(self):
2122
return "<Action: {}>".format(self.ui_class)
2223

2324
def running(self):
24-
return self.ui is not None
25+
return self._running
2526

2627

2728
class IDAAction(Action, ida_kernwin.action_handler_t):
@@ -123,6 +124,7 @@ def activate(self, ctx):
123124
del ctx
124125
if self.running():
125126
return
127+
self._running = True
126128

127129
if callable(self.ui_class):
128130
self.ui = self.ui_class(accept_handler=self.accept_handler,
@@ -131,32 +133,15 @@ def activate(self, ctx):
131133
submit_handler=self.submit_handler,
132134
response_handler=self.response_handler,
133135
exception_handler=self.exception_handler)
134-
self.ui.finished.connect(self.close_dialog)
135136
self.ui.show()
136137
else:
137138
raise NotImplementedError("activation called on an action class with no "
138139
"ui_class defined")
139140

140-
def close_dialog(self):
141-
"""Destruction and cleanup of dialog bound to action on activation
142-
143-
This is called when dialog is finished for whatever reason, It is
144-
guerenteed to be called after `self.finish_handler` due to slot execution
145-
order since Qt4.6"""
146-
log('action_base').info("Action finished: %s", self)
147-
148-
del self.ui
149-
self.ui = None
150-
151-
self.force_update()
152-
153-
@staticmethod
154-
def force_update():
155-
"""Forcefuly requests IDA kernel to update all widgets and views. Useful
156-
for when delayed actions modify the program and/or plugin state without
157-
IDA's awareness"""
158-
iwid_all = 0xFFFFFFFF
159-
ida_kernwin.request_refresh(iwid_all)
141+
def finish_handler(self, status):
142+
del status
143+
log('actions').info("Action finished: %s", self)
144+
self._running = False
160145

161146

162147
class IdbAction(IDAAction):

idaplugin/rematch/actions/match.py

+10-13
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class MatchAction(base.BoundFileAction):
1818

1919
def __init__(self, *args, **kwargs):
2020
super(MatchAction, self).__init__(*args, **kwargs)
21-
self._running = False
2221
self.functions = None
2322
self.results = None
2423
self.task_id = None
@@ -40,9 +39,6 @@ def __init__(self, *args, **kwargs):
4039
self.pbar = None
4140
self.timer = QtCore.QTimer()
4241

43-
def running(self):
44-
return super(MatchAction, self).running() or self._running
45-
4642
def clean(self):
4743
self.timer.stop()
4844
try:
@@ -58,15 +54,13 @@ def clean(self):
5854

5955
def cancel_delayed(self):
6056
for delayed in self.delayed_queries:
61-
log('match_action').info("async task cancelled: %s", repr(delayed))
6257
delayed.cancel()
6358
self.delayed_queries = []
6459

6560
def cancel(self):
6661
log('match_action').info("match action cancelled")
6762
self.clean()
6863
self.cancel_delayed()
69-
self._running = False
7064

7165
@staticmethod
7266
def calc_file_version_hash():
@@ -146,6 +140,8 @@ def perform_upload(self):
146140
q = network.QueryWorker("POST", "collab/instances/",
147141
params=self.instance_set, json=True)
148142
q.start(self.progress_advance)
143+
self.delayed_queries.append(q)
144+
149145
self.instance_set = []
150146
self.pbar.setMaximum(self.pbar.maximum() + 1)
151147
self.progress_advance()
@@ -162,7 +158,7 @@ def accept_upload(self):
162158
log('match_action').info("Data upload completed successfully")
163159

164160
self.clean()
165-
self.delayed_queries = []
161+
self.cancel_delayed()
166162

167163
self.start_task()
168164

@@ -211,6 +207,7 @@ def perform_task(self):
211207
status = r['status']
212208
if status == 'failed':
213209
self.cancel()
210+
# TODO: task failed, print a message box saying so
214211
elif progress_max:
215212
self.pbar.setMaximum(progress_max)
216213
if progress >= progress_max:
@@ -226,7 +223,7 @@ def accept_task(self):
226223
log('match_action').info("Remote task completed successfully")
227224

228225
self.clean()
229-
self.delayed_queries = []
226+
self.cancel_delayed()
230227

231228
self.start_results()
232229

@@ -294,16 +291,16 @@ def handle_page(self, response, page_type):
294291
self.pbar.setValue(self.pbar.value() + 1)
295292

296293
self.pbar.setValue(self.pbar.value() + len(response['results']))
297-
log('match_action').info("result download progress: {} / {} with {}"
298-
"".format(self.pbar.value(), self.pbar.maximum(),
299-
self.seen))
294+
# log('match_action').info("result download progress: {} / {} with {}"
295+
# "".format(self.pbar.value(), self.pbar.maximum(),
296+
# self.seen))
300297
if self.pbar.value() >= self.pbar.maximum():
301298
self.pbar.accept()
302299

303300
def accept_results(self):
304-
log('match_action').info("Result download completed successfully")
301+
# log('match_action').info("Result download completed successfully")
305302

306303
self.clean()
307-
self.delayed_queries = []
304+
self.cancel_delayed()
308305

309306
self.results.show()

idaplugin/rematch/actions/settings.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
import idaapi
22

33
from . import base
4-
from .. import config
4+
from .. import config, netnode
55

66

77
class SettingsAction(base.IDAAction):
88
name = "&Settings"
99

1010
@staticmethod
11-
def submit_handler(autocheck, autoupdate, autologin, autologout, debug):
11+
def submit_handler(autocheck, autoupdate, autologin, autologout, debug,
12+
bound_file):
1213
config['settings']['update']['autocheck'] = autocheck
1314
config['settings']['update']['autoupdate'] = autoupdate
1415
config['settings']['login']['autologin'] = autologin
1516
config['settings']['login']['autologout'] = autologout
1617
config['debug'] = debug
1718
config.save()
1819

20+
netnode.bound_file_id = bound_file
21+
1922
return True
2023

2124
@staticmethod

idaplugin/rematch/collectors/__init__.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
import json
77

88

9-
def collect(collectors, offset, instance_id=None):
10-
for collector in collectors:
9+
def collect(collectors, offset):
10+
for collector_cls in collectors:
1111
try:
12-
collector_obj = collector(offset, instance_id)
13-
r = collector_obj.collect()
12+
r = collector_cls(offset).serialize()
1413
if r:
1514
yield r
1615
except UnicodeDecodeError:
1716
log('annotation').error("Unicode decoding error during serializion of "
18-
"type %s at offset %x", collector.type, offset)
17+
"type %s at offset %x", collector_cls.type,
18+
offset)
1919

2020

2121
def apply(offset, annotation):
@@ -27,7 +27,7 @@ def apply(offset, annotation):
2727

2828
annotation_data = json.loads(annotation['data'])
2929

30-
if annotation_cls.data(offset) == annotation_data:
30+
if annotation_cls(offset).data() == annotation_data:
3131
log('annotation_apply').info("Setting annotation %s skipped at %s with "
3232
"%s because value is already set",
3333
annotation_cls, offset, annotation_data)
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
1-
import json
1+
from .. import collector
22

33

4-
class Annotation(object):
5-
@classmethod
6-
def collect(cls, offset, instance_id=None):
7-
data = cls.data(offset)
8-
if not data:
9-
return None
10-
11-
data = json.dumps(data)
12-
return {"instance": instance_id, "type": cls.type, "data": data}
4+
class Annotation(collector.Collector):
5+
pass

idaplugin/rematch/collectors/annotations/assembly.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@
1313
class AssemblyAnnotation(annotation.Annotation):
1414
type = 'assembly'
1515

16-
@staticmethod
17-
def data(offset):
18-
func = ida_funcs.get_func(offset)
16+
def data(self):
17+
func = ida_funcs.get_func(self.offset)
1918

2019
def clean(asm):
2120
"""This removes markers of function offsets, including hidden variable
@@ -51,6 +50,5 @@ def node_contained(node):
5150
return nodes_data
5251

5352
@staticmethod
54-
def apply(offset, data):
55-
del offset
53+
def apply(data):
5654
del data

0 commit comments

Comments
 (0)