From 48c1ee0770be85dcd2758865bdd5b94ec516fc42 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Wed, 12 Jun 2019 20:14:23 +0000 Subject: [PATCH 1/4] initial work on a mode to create standalone test output automatically --- bin/deepstate/standalone.py | 91 +++++++++++++++++++++++++++++ bin/setup.py.in | 1 + src/include/deepstate/DeepState.hpp | 19 ++++++ 3 files changed, 111 insertions(+) create mode 100644 bin/deepstate/standalone.py diff --git a/bin/deepstate/standalone.py b/bin/deepstate/standalone.py new file mode 100644 index 00000000..56d2206f --- /dev/null +++ b/bin/deepstate/standalone.py @@ -0,0 +1,91 @@ +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import print_function +import argparse + + +def main(): + global candidateRuns, currentTest, s, passStart + + parser = argparse.ArgumentParser(description="Intelligently reduce test case") + + parser.add_argument( + "source", type=str, help="Path to input harness file.") + parser.add_argument( + "output_source", type=str, help="Path to output modified harness file.") + parser.add_argument( + "config", type=str, help="Path for configuration file listing functions to export to standalone.") + + args = parser.parse_args() + + functions = [] + + def annotate(call, f): + annotated = "" + pos = 0 + for c in call: + if c.isspace(): + annotated += c + pos += 1 + else: + break + arguments = call.split(f + "(")[1] + arguments = arguments.split(")")[0] + theArgs = arguments.split(",") + annotated += "LOG(TRACE) << " + annotated += '"/* START CODE: */ ' + call[pos:call.find("(") + 1] + '" << ' + if f != "assert": + for arg in theArgs[:-1]: + annotated += ("DeepState_Standalone_Wrap(" + arg + ') << "," << ') + if len(theArgs) >= 1: + annotated += ("DeepState_Standalone_Wrap(" + theArgs[-1] + ') << ') + else: + for i in range(1, len(call)): + if call[-i] == ")": + endPos = i + break + annotated += '"' + call[call.find("(")+1:-endPos] + '" << ' + annotated += '"); // STANDALONE UNIT TEST CODE";\n' + return annotated + + with open(args.config, 'r') as cfile: + for line in cfile: + functions.append(line.split()[0]) + + for f in functions: + print("ADDING STANDALONE TEST GENERATION CODE FOR", f) + + functions.append("assert") + + oldSource = [] + with open(args.source, 'r') as sfile: + for line in sfile: + oldSource.append(line); + + newSource = [] + inTests = False + for line in oldSource: + if inTests: + for f in functions: + if f+"(" in line: + print("ADDING TEST GENERATION CODE FOR:", line[:-1]) + a = annotate(line, f) + print(a) + newSource.append(a) + elif "TEST(" in line: + inTests = True + newSource.append(line) + + with open(args.output_source, 'w') as nsfile: + for line in newSource: + nsfile.write(line) + +if "__main__" == __name__: + exit(main()) diff --git a/bin/setup.py.in b/bin/setup.py.in index 1bcb41fd..05dc8f98 100644 --- a/bin/setup.py.in +++ b/bin/setup.py.in @@ -37,6 +37,7 @@ setuptools.setup( 'deepstate-angr = deepstate.main_angr:main', 'deepstate-manticore = deepstate.main_manticore:main', 'deepstate-reduce = deepstate.reducer:main', + 'deepstate-generate-standalone-output = deepstate.standalone:main', 'deepstate-eclipser = deepstate.eclipser:main', ] }) diff --git a/src/include/deepstate/DeepState.hpp b/src/include/deepstate/DeepState.hpp index 5e51760b..91ea6a0c 100644 --- a/src/include/deepstate/DeepState.hpp +++ b/src/include/deepstate/DeepState.hpp @@ -116,6 +116,25 @@ DEEPSTATE_INLINE static bool IsSymbolic(double x) { return DeepState_IsSymbolicDouble(x); } +DEEPSTATE_INLINE static int DeepState_Standalone_Wrap(int x) { + return x; +} + +DEEPSTATE_INLINE static unsigned int DeepState_Standalone_Wrap(unsigned int x) { + return x; +} + +DEEPSTATE_INLINE static std::string DeepState_Standalone_Wrap(char* x) { + if (x == NULL) { + return std::string("NULL"); + } else { + std::string s = "\""; + s += std::string(x); + s += "\""; + return s; + } +} + // A test fixture. class Test { public: From 040d1ccce5afe9620401f86386a9dde36fb76092 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Wed, 12 Jun 2019 20:24:37 +0000 Subject: [PATCH 2/4] better output for now until we have new log level --- bin/deepstate/standalone.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bin/deepstate/standalone.py b/bin/deepstate/standalone.py index 56d2206f..d2c5a5eb 100644 --- a/bin/deepstate/standalone.py +++ b/bin/deepstate/standalone.py @@ -30,9 +30,10 @@ def main(): def annotate(call, f): annotated = "" pos = 0 + spaces = "" for c in call: if c.isspace(): - annotated += c + spaces += c pos += 1 else: break @@ -40,7 +41,7 @@ def annotate(call, f): arguments = arguments.split(")")[0] theArgs = arguments.split(",") annotated += "LOG(TRACE) << " - annotated += '"/* START CODE: */ ' + call[pos:call.find("(") + 1] + '" << ' + annotated += '"/* START STANDALONE CODE */' + spaces + call[pos:call.find("(") + 1] + '" << ' if f != "assert": for arg in theArgs[:-1]: annotated += ("DeepState_Standalone_Wrap(" + arg + ') << "," << ') @@ -52,7 +53,7 @@ def annotate(call, f): endPos = i break annotated += '"' + call[call.find("(")+1:-endPos] + '" << ' - annotated += '"); // STANDALONE UNIT TEST CODE";\n' + annotated += '"); /* END STANDALONE CODE */";\n' return annotated with open(args.config, 'r') as cfile: From 0840e17d98ba2eb1367a3184794a526362e96c51 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Thu, 13 Jun 2019 14:57:38 +0000 Subject: [PATCH 3/4] nicer output, new name, help fixed --- bin/deepstate/standalone.py | 4 ++-- bin/setup.py.in | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/deepstate/standalone.py b/bin/deepstate/standalone.py index d2c5a5eb..ecc53c2f 100644 --- a/bin/deepstate/standalone.py +++ b/bin/deepstate/standalone.py @@ -14,7 +14,7 @@ def main(): global candidateRuns, currentTest, s, passStart - parser = argparse.ArgumentParser(description="Intelligently reduce test case") + parser = argparse.ArgumentParser(description="Add code to a DeepState harness to dump code for standalone test cases") parser.add_argument( "source", type=str, help="Path to input harness file.") @@ -44,7 +44,7 @@ def annotate(call, f): annotated += '"/* START STANDALONE CODE */' + spaces + call[pos:call.find("(") + 1] + '" << ' if f != "assert": for arg in theArgs[:-1]: - annotated += ("DeepState_Standalone_Wrap(" + arg + ') << "," << ') + annotated += ("DeepState_Standalone_Wrap(" + arg + ') << ", " << ') if len(theArgs) >= 1: annotated += ("DeepState_Standalone_Wrap(" + theArgs[-1] + ') << ') else: diff --git a/bin/setup.py.in b/bin/setup.py.in index 05dc8f98..7fa6fef4 100644 --- a/bin/setup.py.in +++ b/bin/setup.py.in @@ -37,7 +37,7 @@ setuptools.setup( 'deepstate-angr = deepstate.main_angr:main', 'deepstate-manticore = deepstate.main_manticore:main', 'deepstate-reduce = deepstate.reducer:main', - 'deepstate-generate-standalone-output = deepstate.standalone:main', + 'deepstate-add-standalone = deepstate.standalone:main', 'deepstate-eclipser = deepstate.eclipser:main', ] }) From f08be14c40983a31b82a0302a5561b67d0bb0612 Mon Sep 17 00:00:00 2001 From: Alex Groce Date: Thu, 13 Jun 2019 15:23:21 +0000 Subject: [PATCH 4/4] extraction tool added --- bin/deepstate/extract.py | 52 ++++++++++++++++++++++++++++++++++++++++ bin/setup.py.in | 1 + 2 files changed, 53 insertions(+) create mode 100644 bin/deepstate/extract.py diff --git a/bin/deepstate/extract.py b/bin/deepstate/extract.py new file mode 100644 index 00000000..89c72171 --- /dev/null +++ b/bin/deepstate/extract.py @@ -0,0 +1,52 @@ +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import print_function +import argparse + + +def main(): + global candidateRuns, currentTest, s, passStart + + parser = argparse.ArgumentParser(description="Extract standalone test information from a DeepState harness run") + + parser.add_argument( + "run", type=str, help="Path to DeepState run output.") + parser.add_argument( + "template", type=str, help="Path to test template.") + parser.add_argument( + "output_file", type=str, help="Path to output standalone test.") + + args = parser.parse_args() + + run = [] + with open(args.run, 'r') as rfile: + for line in rfile: + run.append(line) + + newSource = [] + with open(args.template, 'r') as tfile: + for line in tfile: + if "<>" not in line: + newSource.append(line) + else: + for line in run: + if "/* START STANDALONE CODE */" in line: + newLine = line.split("/* START STANDALONE CODE */")[1] + newLine = newLine.split("/* END STANDALONE CODE */")[0] + newLine += "\n" + print(newLine[:-1]) + newSource.append(newLine) + + with open(args.output_file, 'w') as ntfile: + for line in newSource: + ntfile.write(line) + +if "__main__" == __name__: + exit(main()) diff --git a/bin/setup.py.in b/bin/setup.py.in index 7fa6fef4..3e9bf033 100644 --- a/bin/setup.py.in +++ b/bin/setup.py.in @@ -38,6 +38,7 @@ setuptools.setup( 'deepstate-manticore = deepstate.main_manticore:main', 'deepstate-reduce = deepstate.reducer:main', 'deepstate-add-standalone = deepstate.standalone:main', + 'deepstate-extract-standalone = deepstate.extract:main', 'deepstate-eclipser = deepstate.eclipser:main', ] })