sflkit 0.5.0__tar.gz → 0.5.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sflkit-0.5.0/src/sflkit.egg-info → sflkit-0.5.1}/PKG-INFO +2 -2
- {sflkit-0.5.0 → sflkit-0.5.1}/pyproject.toml +1 -1
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/__init__.py +1 -1
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/analysis/analysis_type.py +13 -13
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/analysis/analyzer.py +14 -4
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/analysis/factory.py +166 -89
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/analysis/predicate.py +86 -63
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/analysis/similarity.py +1 -1
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/analysis/spectra.py +100 -49
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/events/event_file.py +8 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/features/handler.py +55 -24
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/features/value.py +26 -5
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/features/vector.py +27 -14
- sflkit-0.5.1/src/sflkit/model/model.py +150 -0
- sflkit-0.5.1/src/sflkit/model/parallel.py +97 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/runners/run.py +49 -50
- sflkit-0.5.1/src/sflkit/weights/models.py +329 -0
- {sflkit-0.5.0 → sflkit-0.5.1/src/sflkit.egg-info}/PKG-INFO +2 -2
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit.egg-info/SOURCES.txt +1 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit.egg-info/requires.txt +1 -1
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_cli.py +2 -1
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_config.py +2 -2
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_dependency_weights.py +4 -2
- sflkit-0.5.1/tests/test_features.py +451 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_runner.py +1 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_runner_parallel.py +3 -1
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_suggestions.py +2 -0
- sflkit-0.5.0/src/sflkit/model/model.py +0 -114
- sflkit-0.5.0/src/sflkit/model/parallel.py +0 -127
- sflkit-0.5.0/src/sflkit/weights/models.py +0 -300
- {sflkit-0.5.0 → sflkit-0.5.1}/LICENSE +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/README.md +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/setup.cfg +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/analysis/__init__.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/analysis/mapping.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/analysis/suggestion.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/cli.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/color.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/config.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/evaluation.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/events/__init__.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/events/mapping.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/features/__init__.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/instrumentation/__init__.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/instrumentation/dir_instrumentation.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/instrumentation/file_instrumentation.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/__init__.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/extract.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/finder.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/java/__init__.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/java/extract.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/java/factory.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/java/finder.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/java/visitor.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/language.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/meta.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/python/__init__.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/python/extract.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/python/factory.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/python/finder.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/python/visitor.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/language/visitor.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/logger.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/model/__init__.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/model/scope.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/runners/__init__.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/weights/__init__.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit/weights/analyzer.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit.egg-info/dependency_links.txt +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit.egg-info/entry_points.txt +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/src/sflkit.egg-info/top_level.txt +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_analysis_objects.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_analyzer.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_color.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_coverage.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_evaluation.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_events.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_execution.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_instrumentation.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_language.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_parallelization.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_predicates.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_runner_pytest_versions.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_scope.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_spectra.py +0 -0
- {sflkit-0.5.0 → sflkit-0.5.1}/tests/test_visitors.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sflkit
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: SFLKit: : A Workbench for Statistical Fault Localization
|
|
5
5
|
Author-email: Marius Smytzek <marius.smytzek@cispa.de>
|
|
6
6
|
Project-URL: Homepage, https://github.com/smythi93/sflkit/
|
|
@@ -15,7 +15,7 @@ Classifier: Topic :: Software Development :: Testing
|
|
|
15
15
|
Requires-Python: >=3.10
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: sflkitlib>=0.2.
|
|
18
|
+
Requires-Dist: sflkitlib>=0.2.2
|
|
19
19
|
Requires-Dist: numpy>=2.1.3
|
|
20
20
|
Requires-Dist: matplotlib>=3.10.0
|
|
21
21
|
Requires-Dist: pandas>=2.2.3
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import abc
|
|
1
2
|
import enum
|
|
2
|
-
from
|
|
3
|
-
from typing import List, Type, Optional
|
|
3
|
+
from typing import List, Type, Optional, Any
|
|
4
4
|
|
|
5
5
|
from sflkit.events.event_file import EventFile
|
|
6
6
|
from sflkit.model.scope import Scope
|
|
@@ -43,7 +43,7 @@ If you want to add new spectra or predicates, please register them here and in s
|
|
|
43
43
|
"""
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
class AnalysisObject:
|
|
46
|
+
class AnalysisObject(abc.ABC):
|
|
47
47
|
function_finder = None
|
|
48
48
|
loop_finder = None
|
|
49
49
|
branch_finder = None
|
|
@@ -58,17 +58,17 @@ class AnalysisObject:
|
|
|
58
58
|
def __init__(self):
|
|
59
59
|
self.suspiciousness: float = 0
|
|
60
60
|
self.last_evaluation: EvaluationResult = EvaluationResult.UNOBSERVED
|
|
61
|
-
self.hits = dict()
|
|
61
|
+
self.hits: dict[EventFile, dict[Optional[int], Any]] = dict()
|
|
62
62
|
|
|
63
63
|
def adjust_weight(self, event_file: EventFile, weight: float):
|
|
64
64
|
pass
|
|
65
65
|
|
|
66
|
-
@abstractmethod
|
|
66
|
+
@abc.abstractmethod
|
|
67
67
|
def serialize(self) -> dict:
|
|
68
68
|
pass
|
|
69
69
|
|
|
70
70
|
@staticmethod
|
|
71
|
-
@abstractmethod
|
|
71
|
+
@abc.abstractmethod
|
|
72
72
|
def deserialize(s: dict) -> "AnalysisObject":
|
|
73
73
|
pass
|
|
74
74
|
|
|
@@ -82,7 +82,7 @@ class AnalysisObject:
|
|
|
82
82
|
return f"{self.analysis_type()}"
|
|
83
83
|
|
|
84
84
|
@staticmethod
|
|
85
|
-
@abstractmethod
|
|
85
|
+
@abc.abstractmethod
|
|
86
86
|
def analysis_type() -> AnalysisType:
|
|
87
87
|
raise NotImplementedError()
|
|
88
88
|
|
|
@@ -93,19 +93,19 @@ class AnalysisObject:
|
|
|
93
93
|
def calculate(self):
|
|
94
94
|
pass
|
|
95
95
|
|
|
96
|
-
@abstractmethod
|
|
96
|
+
@abc.abstractmethod
|
|
97
97
|
def finalize(self, passed: List, failed: List):
|
|
98
98
|
raise NotImplementedError()
|
|
99
99
|
|
|
100
|
-
@abstractmethod
|
|
101
|
-
def hit(self, id_, event,
|
|
100
|
+
@abc.abstractmethod
|
|
101
|
+
def hit(self, id_: EventFile, event, scope: Scope = None):
|
|
102
102
|
raise NotImplementedError()
|
|
103
103
|
|
|
104
|
-
@abstractmethod
|
|
104
|
+
@abc.abstractmethod
|
|
105
105
|
def get_suggestion(self):
|
|
106
106
|
raise NotImplementedError()
|
|
107
107
|
|
|
108
|
-
@abstractmethod
|
|
108
|
+
@abc.abstractmethod
|
|
109
109
|
def assign_suspiciousness(self):
|
|
110
110
|
raise NotImplementedError()
|
|
111
111
|
|
|
@@ -114,7 +114,7 @@ class AnalysisObject:
|
|
|
114
114
|
return any(map(lambda e: isinstance(event, e), events))
|
|
115
115
|
|
|
116
116
|
@staticmethod
|
|
117
|
-
@abstractmethod
|
|
117
|
+
@abc.abstractmethod
|
|
118
118
|
def events() -> List[Type]:
|
|
119
119
|
raise NotImplementedError()
|
|
120
120
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
3
4
|
from typing import List, Callable, Set, Dict, Optional, Any, Type
|
|
4
5
|
|
|
5
6
|
from sflkit.analysis.analysis_type import AnalysisType, AnalysisObject
|
|
@@ -42,6 +43,7 @@ class Analyzer:
|
|
|
42
43
|
meta_model: Optional[MetaModel] = None,
|
|
43
44
|
model_class: Type[Model] = None,
|
|
44
45
|
parallel: bool = False,
|
|
46
|
+
workers: int = 4,
|
|
45
47
|
):
|
|
46
48
|
if (
|
|
47
49
|
relevant_event_files is None
|
|
@@ -64,6 +66,7 @@ class Analyzer:
|
|
|
64
66
|
else:
|
|
65
67
|
model_class = Model
|
|
66
68
|
self.model = model_class(factory)
|
|
69
|
+
self.workers = workers
|
|
67
70
|
self.paths: Dict[int, os.PathLike] = dict()
|
|
68
71
|
self.max_suspiciousness = 0
|
|
69
72
|
self.min_suspiciousness = 0
|
|
@@ -76,7 +79,7 @@ class Analyzer:
|
|
|
76
79
|
self.model.prepare(event_file)
|
|
77
80
|
with event_file:
|
|
78
81
|
for event in event_file.load():
|
|
79
|
-
event.handle(self.model)
|
|
82
|
+
event.handle(self.model, event_file)
|
|
80
83
|
self.model.follow_up(event_file)
|
|
81
84
|
|
|
82
85
|
def _finalize(self):
|
|
@@ -87,9 +90,16 @@ class Analyzer:
|
|
|
87
90
|
def analyze(self):
|
|
88
91
|
if self.meta:
|
|
89
92
|
raise NotImplementedError("Not implemented for meta/loaded analyzer")
|
|
90
|
-
|
|
91
|
-
self.
|
|
92
|
-
|
|
93
|
+
if self.workers > 1:
|
|
94
|
+
event_files = self.relevant_event_files + self.irrelevant_event_files
|
|
95
|
+
for event_file in event_files:
|
|
96
|
+
self.paths[event_file.run_id] = event_file.path
|
|
97
|
+
with ThreadPoolExecutor(max_workers=self.workers) as executor:
|
|
98
|
+
list(executor.map(self._analyze, event_files))
|
|
99
|
+
else:
|
|
100
|
+
for event_file in self.relevant_event_files + self.irrelevant_event_files:
|
|
101
|
+
self.paths[event_file.run_id] = event_file.path
|
|
102
|
+
self._analyze(event_file)
|
|
93
103
|
self._finalize()
|
|
94
104
|
|
|
95
105
|
def dump(self, path: os.PathLike, indent: Optional[int] = None):
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import abc
|
|
2
|
-
from
|
|
2
|
+
from threading import Lock
|
|
3
3
|
from typing import List, Type, Set
|
|
4
4
|
|
|
5
5
|
from sflkitlib.events import EventType
|
|
6
|
+
from sflkitlib.events.event import DefEvent
|
|
6
7
|
|
|
7
8
|
from sflkit.analysis.analysis_type import AnalysisObject, AnalysisType
|
|
8
9
|
from sflkit.analysis.predicate import (
|
|
@@ -21,25 +22,29 @@ from sflkit.analysis.predicate import (
|
|
|
21
22
|
FunctionErrorPredicate,
|
|
22
23
|
)
|
|
23
24
|
from sflkit.analysis.spectra import Line, Function, Loop, DefUse, Length
|
|
25
|
+
from sflkit.events.event_file import EventFile
|
|
24
26
|
from sflkit.model.scope import Scope
|
|
25
27
|
|
|
26
28
|
|
|
27
|
-
class AnalysisFactory:
|
|
29
|
+
class AnalysisFactory(abc.ABC):
|
|
28
30
|
def __init__(self):
|
|
29
31
|
self.objects = dict()
|
|
32
|
+
self._lock = Lock()
|
|
30
33
|
|
|
31
|
-
@abstractmethod
|
|
32
|
-
def get_analysis(
|
|
34
|
+
@abc.abstractmethod
|
|
35
|
+
def get_analysis(
|
|
36
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
37
|
+
) -> List[AnalysisObject]:
|
|
33
38
|
raise NotImplementedError()
|
|
34
39
|
|
|
35
|
-
def handle(self, event, scope: Scope = None):
|
|
36
|
-
analysis = self.get_analysis(event, scope=scope)
|
|
40
|
+
def handle(self, event, event_file: EventFile, scope: Scope = None):
|
|
41
|
+
analysis = self.get_analysis(event, event_file, scope=scope)
|
|
37
42
|
if analysis:
|
|
38
43
|
return analysis
|
|
39
44
|
else:
|
|
40
45
|
return self.default()
|
|
41
46
|
|
|
42
|
-
def reset(self):
|
|
47
|
+
def reset(self, event_file: EventFile):
|
|
43
48
|
pass
|
|
44
49
|
|
|
45
50
|
@staticmethod
|
|
@@ -55,25 +60,32 @@ class CombinationFactory(AnalysisFactory):
|
|
|
55
60
|
super().__init__()
|
|
56
61
|
self.factories = factories
|
|
57
62
|
|
|
58
|
-
def get_analysis(
|
|
63
|
+
def get_analysis(
|
|
64
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
65
|
+
) -> List[AnalysisObject]:
|
|
59
66
|
return sum(
|
|
60
|
-
[factory.handle(event, scope) for factory in self.factories],
|
|
67
|
+
[factory.handle(event, event_file, scope) for factory in self.factories],
|
|
68
|
+
start=list(),
|
|
61
69
|
)
|
|
62
70
|
|
|
63
|
-
def reset(self):
|
|
64
|
-
[f.reset() for f in self.factories]
|
|
71
|
+
def reset(self, event_file: EventFile):
|
|
72
|
+
[f.reset(event_file) for f in self.factories]
|
|
65
73
|
|
|
66
74
|
def get_all(self) -> Set[AnalysisObject]:
|
|
67
75
|
return set().union(*map(lambda f: f.get_all(), self.factories))
|
|
68
76
|
|
|
69
77
|
|
|
70
78
|
class LineFactory(AnalysisFactory):
|
|
71
|
-
def get_analysis(
|
|
79
|
+
def get_analysis(
|
|
80
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
81
|
+
) -> List[AnalysisObject]:
|
|
72
82
|
if event.event_type == EventType.LINE:
|
|
73
83
|
key = (Line.analysis_type(), event.file, event.line)
|
|
74
|
-
|
|
75
|
-
self.objects
|
|
84
|
+
with self._lock:
|
|
85
|
+
if key not in self.objects:
|
|
86
|
+
self.objects[key] = Line(event)
|
|
76
87
|
return [self.objects[key]]
|
|
88
|
+
return None
|
|
77
89
|
|
|
78
90
|
|
|
79
91
|
class BranchFactory(AnalysisFactory):
|
|
@@ -81,12 +93,15 @@ class BranchFactory(AnalysisFactory):
|
|
|
81
93
|
super().__init__()
|
|
82
94
|
self.else_ = else_
|
|
83
95
|
|
|
84
|
-
def get_analysis(
|
|
96
|
+
def get_analysis(
|
|
97
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
98
|
+
) -> List[AnalysisObject]:
|
|
85
99
|
if event.event_type == EventType.BRANCH:
|
|
86
100
|
key = (Branch.analysis_type(), event.file, event.line, event.then_id)
|
|
87
101
|
then = event.then_id < event.else_id
|
|
88
|
-
|
|
89
|
-
|
|
102
|
+
with self._lock:
|
|
103
|
+
if key not in self.objects:
|
|
104
|
+
self.objects[key] = Branch(event, then=then, then_id=event.then_id)
|
|
90
105
|
if self.else_ and event.else_id >= 0:
|
|
91
106
|
else_key = (
|
|
92
107
|
Branch.analysis_type(),
|
|
@@ -94,19 +109,28 @@ class BranchFactory(AnalysisFactory):
|
|
|
94
109
|
event.line,
|
|
95
110
|
event.else_id,
|
|
96
111
|
)
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
with self._lock:
|
|
113
|
+
if else_key not in self.objects:
|
|
114
|
+
self.objects[else_key] = Branch(
|
|
115
|
+
event, then=not then, then_id=event.else_id
|
|
116
|
+
)
|
|
99
117
|
return [self.objects[key], self.objects[else_key]]
|
|
100
118
|
return [self.objects[key]]
|
|
101
119
|
|
|
120
|
+
return None
|
|
121
|
+
|
|
102
122
|
|
|
103
123
|
class FunctionFactory(AnalysisFactory):
|
|
104
|
-
def get_analysis(
|
|
124
|
+
def get_analysis(
|
|
125
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
126
|
+
) -> List[AnalysisObject]:
|
|
105
127
|
if event.event_type == EventType.FUNCTION_ENTER:
|
|
106
128
|
key = (Function.analysis_type(), event.file, event.line, event.function_id)
|
|
107
|
-
|
|
108
|
-
self.objects
|
|
129
|
+
with self._lock:
|
|
130
|
+
if key not in self.objects:
|
|
131
|
+
self.objects[key] = Function(event)
|
|
109
132
|
return [self.objects[key]]
|
|
133
|
+
return None
|
|
110
134
|
|
|
111
135
|
|
|
112
136
|
class LoopFactory(AnalysisFactory):
|
|
@@ -119,60 +143,72 @@ class LoopFactory(AnalysisFactory):
|
|
|
119
143
|
def get_all(self) -> Set[AnalysisObject]:
|
|
120
144
|
return set(obj for value in self.objects.values() for obj in value)
|
|
121
145
|
|
|
122
|
-
def get_analysis(
|
|
146
|
+
def get_analysis(
|
|
147
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
148
|
+
) -> List[AnalysisObject]:
|
|
123
149
|
if event.event_type in (
|
|
124
150
|
EventType.LOOP_BEGIN,
|
|
125
151
|
EventType.LOOP_HIT,
|
|
126
152
|
EventType.LOOP_END,
|
|
127
153
|
):
|
|
128
154
|
key = (Loop.analysis_type(), event.file, event.line, event.loop_id)
|
|
129
|
-
|
|
130
|
-
self.objects
|
|
131
|
-
|
|
132
|
-
self.
|
|
133
|
-
|
|
134
|
-
self.
|
|
135
|
-
|
|
136
|
-
self.
|
|
155
|
+
with self._lock:
|
|
156
|
+
if key not in self.objects:
|
|
157
|
+
self.objects[key] = []
|
|
158
|
+
if self.hit_0:
|
|
159
|
+
self.objects[key].append(Loop(event, Loop.evaluate_hit_0)),
|
|
160
|
+
if self.hit_1:
|
|
161
|
+
self.objects[key].append(Loop(event, Loop.evaluate_hit_1)),
|
|
162
|
+
if self.hit_more:
|
|
163
|
+
self.objects[key].append(Loop(event, Loop.evaluate_hit_more)),
|
|
137
164
|
if event.event_type == EventType.LOOP_BEGIN:
|
|
138
|
-
|
|
165
|
+
for obj in self.objects[key]:
|
|
166
|
+
obj.start_loop(thread_id=event.thread_id)
|
|
139
167
|
elif event.event_type == EventType.LOOP_HIT:
|
|
140
|
-
|
|
168
|
+
for obj in self.objects[key]:
|
|
169
|
+
obj.hit_loop(thread_id=event.thread_id)
|
|
141
170
|
elif event.event_type == EventType.LOOP_END:
|
|
142
171
|
return self.objects[key][:]
|
|
143
172
|
return list()
|
|
173
|
+
return None
|
|
144
174
|
|
|
145
175
|
|
|
146
176
|
class DefUseFactory(AnalysisFactory):
|
|
147
177
|
def __init__(self):
|
|
148
178
|
super().__init__()
|
|
149
|
-
self.id_to_def = dict()
|
|
179
|
+
self.id_to_def: dict[EventFile, dict[tuple[str, int], DefEvent]] = dict()
|
|
150
180
|
|
|
151
|
-
def reset(self):
|
|
152
|
-
self.id_to_def = dict()
|
|
181
|
+
def reset(self, event_file: EventFile):
|
|
182
|
+
self.id_to_def[event_file] = dict()
|
|
153
183
|
|
|
154
|
-
def get_analysis(
|
|
184
|
+
def get_analysis(
|
|
185
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
186
|
+
) -> List[AnalysisObject]:
|
|
155
187
|
if event.event_type == EventType.DEF:
|
|
156
|
-
self.id_to_def[(event.var, event.var_id)] = event
|
|
188
|
+
self.id_to_def[event_file][(event.var, event.var_id)] = event
|
|
157
189
|
elif event.event_type == EventType.USE:
|
|
158
|
-
if (event.var, event.var_id) in self.id_to_def:
|
|
190
|
+
if (event.var, event.var_id) in self.id_to_def[event_file]:
|
|
159
191
|
key = (
|
|
160
192
|
DefUse.analysis_type(),
|
|
161
|
-
self.id_to_def[(event.var, event.var_id)].file,
|
|
162
|
-
self.id_to_def[(event.var, event.var_id)].line,
|
|
193
|
+
self.id_to_def[event_file][(event.var, event.var_id)].file,
|
|
194
|
+
self.id_to_def[event_file][(event.var, event.var_id)].line,
|
|
163
195
|
event.file,
|
|
164
196
|
event.line,
|
|
165
197
|
event.var,
|
|
166
198
|
)
|
|
167
|
-
|
|
168
|
-
self.objects
|
|
169
|
-
self.
|
|
170
|
-
|
|
199
|
+
with self._lock:
|
|
200
|
+
if key not in self.objects:
|
|
201
|
+
self.objects[key] = DefUse(
|
|
202
|
+
self.id_to_def[event_file][(event.var, event.var_id)], event
|
|
203
|
+
)
|
|
171
204
|
return [self.objects[key]]
|
|
205
|
+
return None
|
|
172
206
|
|
|
173
207
|
|
|
174
208
|
class ConditionFactory(AnalysisFactory):
|
|
175
|
-
def get_analysis(
|
|
209
|
+
def get_analysis(
|
|
210
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
211
|
+
) -> List[AnalysisObject]:
|
|
176
212
|
objects = list()
|
|
177
213
|
if event.event_type == EventType.CONDITION:
|
|
178
214
|
for negate in (True, False):
|
|
@@ -183,10 +219,11 @@ class ConditionFactory(AnalysisFactory):
|
|
|
183
219
|
event.condition,
|
|
184
220
|
negate,
|
|
185
221
|
)
|
|
186
|
-
|
|
187
|
-
self.objects
|
|
188
|
-
|
|
189
|
-
|
|
222
|
+
with self._lock:
|
|
223
|
+
if key not in self.objects:
|
|
224
|
+
self.objects[key] = Condition(
|
|
225
|
+
event.file, event.line, event.condition, negate=negate
|
|
226
|
+
)
|
|
190
227
|
objects.append(self.objects[key])
|
|
191
228
|
return objects
|
|
192
229
|
|
|
@@ -218,7 +255,9 @@ class ComparisonFactory(AnalysisFactory, abc.ABC):
|
|
|
218
255
|
|
|
219
256
|
|
|
220
257
|
class ScalarPairFactory(ComparisonFactory):
|
|
221
|
-
def get_analysis(
|
|
258
|
+
def get_analysis(
|
|
259
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
260
|
+
) -> List[AnalysisObject]:
|
|
222
261
|
if event.event_type == EventType.DEF:
|
|
223
262
|
variables = scope.get_all_vars()
|
|
224
263
|
objects = list()
|
|
@@ -238,10 +277,11 @@ class ScalarPairFactory(ComparisonFactory):
|
|
|
238
277
|
comp,
|
|
239
278
|
types[0],
|
|
240
279
|
)
|
|
241
|
-
|
|
242
|
-
self.objects
|
|
243
|
-
|
|
244
|
-
|
|
280
|
+
with self._lock:
|
|
281
|
+
if key not in self.objects:
|
|
282
|
+
self.objects[key] = ScalarPair(
|
|
283
|
+
event, comp, variable.var
|
|
284
|
+
)
|
|
245
285
|
objects.append(self.objects[key])
|
|
246
286
|
else:
|
|
247
287
|
for variable in variables:
|
|
@@ -257,16 +297,20 @@ class ScalarPairFactory(ComparisonFactory):
|
|
|
257
297
|
comp,
|
|
258
298
|
event.type_,
|
|
259
299
|
)
|
|
260
|
-
|
|
261
|
-
self.objects
|
|
262
|
-
|
|
263
|
-
|
|
300
|
+
with self._lock:
|
|
301
|
+
if key not in self.objects:
|
|
302
|
+
self.objects[key] = ScalarPair(
|
|
303
|
+
event, comp, variable.var
|
|
304
|
+
)
|
|
264
305
|
objects.append(self.objects[key])
|
|
265
306
|
return objects
|
|
307
|
+
return None
|
|
266
308
|
|
|
267
309
|
|
|
268
310
|
class VariableFactory(ComparisonFactory):
|
|
269
|
-
def get_analysis(
|
|
311
|
+
def get_analysis(
|
|
312
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
313
|
+
) -> List[AnalysisObject]:
|
|
270
314
|
if event.event_type == EventType.DEF and event.type_ in [
|
|
271
315
|
"int",
|
|
272
316
|
"float",
|
|
@@ -282,14 +326,18 @@ class VariableFactory(ComparisonFactory):
|
|
|
282
326
|
comp,
|
|
283
327
|
"int",
|
|
284
328
|
)
|
|
285
|
-
|
|
286
|
-
|
|
329
|
+
with self._lock:
|
|
330
|
+
if key not in self.objects:
|
|
331
|
+
self.objects[key] = VariablePredicate(event, comp)
|
|
287
332
|
objects.append(self.objects[key])
|
|
288
333
|
return objects
|
|
334
|
+
return None
|
|
289
335
|
|
|
290
336
|
|
|
291
337
|
class ReturnFactory(ComparisonFactory):
|
|
292
|
-
def get_analysis(
|
|
338
|
+
def get_analysis(
|
|
339
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
340
|
+
) -> List[AnalysisObject]:
|
|
293
341
|
if event.event_type == EventType.FUNCTION_EXIT:
|
|
294
342
|
objects = list()
|
|
295
343
|
if event.type_ in ("int", "float", "bool", "str", "bytes"):
|
|
@@ -312,8 +360,11 @@ class ReturnFactory(ComparisonFactory):
|
|
|
312
360
|
comp,
|
|
313
361
|
type_,
|
|
314
362
|
)
|
|
315
|
-
|
|
316
|
-
|
|
363
|
+
with self._lock:
|
|
364
|
+
if key not in self.objects:
|
|
365
|
+
self.objects[key] = ReturnPredicate(
|
|
366
|
+
event, comp, value=tr
|
|
367
|
+
)
|
|
317
368
|
objects.append(self.objects[key])
|
|
318
369
|
if event.type_ == "NoneType":
|
|
319
370
|
for comp in Comp.EQ, Comp.NE:
|
|
@@ -326,8 +377,11 @@ class ReturnFactory(ComparisonFactory):
|
|
|
326
377
|
comp,
|
|
327
378
|
event.type_,
|
|
328
379
|
)
|
|
329
|
-
|
|
330
|
-
|
|
380
|
+
with self._lock:
|
|
381
|
+
if key not in self.objects:
|
|
382
|
+
self.objects[key] = ReturnPredicate(
|
|
383
|
+
event, comp, value=None
|
|
384
|
+
)
|
|
331
385
|
objects.append(self.objects[key])
|
|
332
386
|
else:
|
|
333
387
|
for comp in Comp.EQ, Comp.NE:
|
|
@@ -343,6 +397,7 @@ class ReturnFactory(ComparisonFactory):
|
|
|
343
397
|
if key in self.objects:
|
|
344
398
|
objects.append(self.objects[key])
|
|
345
399
|
return objects
|
|
400
|
+
return None
|
|
346
401
|
|
|
347
402
|
|
|
348
403
|
class ConstantCompFactory(AnalysisFactory):
|
|
@@ -350,7 +405,9 @@ class ConstantCompFactory(AnalysisFactory):
|
|
|
350
405
|
super().__init__()
|
|
351
406
|
self.class_ = class_
|
|
352
407
|
|
|
353
|
-
def get_analysis(
|
|
408
|
+
def get_analysis(
|
|
409
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
410
|
+
) -> List[AnalysisObject]:
|
|
354
411
|
if event.event_type == EventType.DEF:
|
|
355
412
|
objects = list()
|
|
356
413
|
for comp in Comp.EQ, Comp.NE:
|
|
@@ -361,10 +418,13 @@ class ConstantCompFactory(AnalysisFactory):
|
|
|
361
418
|
event.var,
|
|
362
419
|
comp,
|
|
363
420
|
)
|
|
364
|
-
|
|
365
|
-
|
|
421
|
+
with self._lock:
|
|
422
|
+
if key not in self.objects:
|
|
423
|
+
# noinspection PyArgumentList
|
|
424
|
+
self.objects[key] = self.class_(event)
|
|
366
425
|
objects.append(self.objects[key])
|
|
367
426
|
return objects
|
|
427
|
+
return None
|
|
368
428
|
|
|
369
429
|
|
|
370
430
|
class NoneFactory(ConstantCompFactory):
|
|
@@ -387,7 +447,9 @@ class PredicateFunctionFactory(AnalysisFactory):
|
|
|
387
447
|
super().__init__()
|
|
388
448
|
self.class_ = class_
|
|
389
449
|
|
|
390
|
-
def get_analysis(
|
|
450
|
+
def get_analysis(
|
|
451
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
452
|
+
) -> List[AnalysisObject]:
|
|
391
453
|
if event.event_type == EventType.DEF:
|
|
392
454
|
key = (
|
|
393
455
|
self.class_.analysis_type(),
|
|
@@ -395,9 +457,12 @@ class PredicateFunctionFactory(AnalysisFactory):
|
|
|
395
457
|
event.line,
|
|
396
458
|
event.var,
|
|
397
459
|
)
|
|
398
|
-
|
|
399
|
-
|
|
460
|
+
with self._lock:
|
|
461
|
+
if key not in self.objects:
|
|
462
|
+
# noinspection PyArgumentList
|
|
463
|
+
self.objects[key] = self.class_(event)
|
|
400
464
|
return [self.objects[key]]
|
|
465
|
+
return None
|
|
401
466
|
|
|
402
467
|
|
|
403
468
|
class IsAsciiFactory(PredicateFunctionFactory):
|
|
@@ -427,20 +492,28 @@ class LengthFactory(AnalysisFactory):
|
|
|
427
492
|
def get_all(self) -> Set[AnalysisObject]:
|
|
428
493
|
return set(obj for value in self.objects.values() for obj in value)
|
|
429
494
|
|
|
430
|
-
def get_analysis(
|
|
495
|
+
def get_analysis(
|
|
496
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
497
|
+
) -> List[AnalysisObject]:
|
|
431
498
|
if event.event_type == EventType.LEN:
|
|
432
499
|
key = (Length.analysis_type(), event.file, event.line, event.var)
|
|
433
|
-
|
|
434
|
-
self.objects
|
|
435
|
-
|
|
436
|
-
self.
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
self.
|
|
441
|
-
|
|
442
|
-
|
|
500
|
+
with self._lock:
|
|
501
|
+
if key not in self.objects:
|
|
502
|
+
self.objects[key] = []
|
|
503
|
+
if self.length_0:
|
|
504
|
+
self.objects[key].append(
|
|
505
|
+
Length(event, Length.evaluate_length_0)
|
|
506
|
+
),
|
|
507
|
+
if self.length_1:
|
|
508
|
+
self.objects[key].append(
|
|
509
|
+
Length(event, Length.evaluate_length_1)
|
|
510
|
+
),
|
|
511
|
+
if self.length_more:
|
|
512
|
+
self.objects[key].append(
|
|
513
|
+
Length(event, Length.evaluate_length_more)
|
|
514
|
+
)
|
|
443
515
|
return self.objects[key][:]
|
|
516
|
+
return None
|
|
444
517
|
|
|
445
518
|
|
|
446
519
|
class FunctionErrorFactory(AnalysisFactory):
|
|
@@ -448,7 +521,9 @@ class FunctionErrorFactory(AnalysisFactory):
|
|
|
448
521
|
super().__init__()
|
|
449
522
|
self.function_mapping = dict()
|
|
450
523
|
|
|
451
|
-
def get_analysis(
|
|
524
|
+
def get_analysis(
|
|
525
|
+
self, event, event_file: EventFile, scope: Scope = None
|
|
526
|
+
) -> List[AnalysisObject]:
|
|
452
527
|
if event.event_type == EventType.FUNCTION_ENTER:
|
|
453
528
|
self.function_mapping[event.function_id] = event.line
|
|
454
529
|
if event.event_type in (EventType.FUNCTION_ERROR, EventType.FUNCTION_EXIT):
|
|
@@ -459,11 +534,13 @@ class FunctionErrorFactory(AnalysisFactory):
|
|
|
459
534
|
line,
|
|
460
535
|
event.function_id,
|
|
461
536
|
)
|
|
462
|
-
|
|
463
|
-
self.objects
|
|
464
|
-
|
|
465
|
-
|
|
537
|
+
with self._lock:
|
|
538
|
+
if key not in self.objects:
|
|
539
|
+
self.objects[key] = FunctionErrorPredicate(
|
|
540
|
+
event.file, line, event.function
|
|
541
|
+
)
|
|
466
542
|
return [self.objects[key]]
|
|
543
|
+
return None
|
|
467
544
|
|
|
468
545
|
|
|
469
546
|
analysis_factory_mapping = {
|