From fa3e3185b75404ac05bd4a6a92cf51d3f0a01393 Mon Sep 17 00:00:00 2001 From: Osogi Date: Fri, 29 May 2026 03:11:04 +0300 Subject: [PATCH 1/9] compiler: add base for tests --- .gitignore | 6 +- src/compiler/meson.build | 4 + src/compiler/meson_options.txt | 1 + src/compiler/subprojects/approvaltests.wrap | 9 ++ .../packagefiles/approvaltests/meson.build | 31 +++++++ src/compiler/tests/README.md | 30 +++++++ .../fixtures/parser/syntax_error.approved.txt | 5 ++ .../tests/fixtures/parser/syntax_error.rule | 3 + .../parser/varnode_pnode_rewrite.approved.txt | 11 +++ .../parser/varnode_pnode_rewrite.rule | 5 ++ .../replace_first_arg.approved.txt | 9 ++ .../rulecompile/replace_first_arg.rule | 3 + .../rulecompile/syntax_error.approved.txt | 5 ++ .../fixtures/rulecompile/syntax_error.rule | 3 + .../validate/replace_first_arg.approved.txt | 10 +++ .../fixtures/validate/replace_first_arg.rule | 3 + .../validate/syntax_error.approved.txt | 5 ++ .../tests/fixtures/validate/syntax_error.rule | 3 + src/compiler/tests/golden_common.cpp | 73 +++++++++++++++ src/compiler/tests/golden_common.hh | 26 ++++++ src/compiler/tests/meson.build | 81 +++++++++++++++++ src/compiler/tests/parser_golden_test.cpp | 51 +++++++++++ .../tests/rulecompile_golden_test.cpp | 90 +++++++++++++++++++ src/compiler/tests/validate_golden_test.cpp | 80 +++++++++++++++++ 24 files changed, 546 insertions(+), 1 deletion(-) create mode 100644 src/compiler/meson_options.txt create mode 100644 src/compiler/subprojects/approvaltests.wrap create mode 100644 src/compiler/subprojects/packagefiles/approvaltests/meson.build create mode 100644 src/compiler/tests/README.md create mode 100644 src/compiler/tests/fixtures/parser/syntax_error.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/syntax_error.rule create mode 100644 src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/replace_first_arg.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/replace_first_arg.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/syntax_error.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/syntax_error.rule create mode 100644 src/compiler/tests/fixtures/validate/replace_first_arg.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/replace_first_arg.rule create mode 100644 src/compiler/tests/fixtures/validate/syntax_error.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/syntax_error.rule create mode 100644 src/compiler/tests/golden_common.cpp create mode 100644 src/compiler/tests/golden_common.hh create mode 100644 src/compiler/tests/meson.build create mode 100644 src/compiler/tests/parser_golden_test.cpp create mode 100644 src/compiler/tests/rulecompile_golden_test.cpp create mode 100644 src/compiler/tests/validate_golden_test.cpp diff --git a/.gitignore b/.gitignore index 94a5ed8..df2bb80 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,8 @@ src/publisher/parse/parser.cc src/publisher/parse/location.hh .codex tmp -AGENTS.md \ No newline at end of file +AGENTS.md +src/compiler/subprojects/.wraplock +src/compiler/subprojects/approvaltests/ +src/compiler/subprojects/packagecache/ +src/compiler/tests/**/*.received.* diff --git a/src/compiler/meson.build b/src/compiler/meson.build index 2430a45..b1eaaab 100644 --- a/src/compiler/meson.build +++ b/src/compiler/meson.build @@ -37,3 +37,7 @@ subdir('validate') subdir('rulecompile') subdir('bin') + +if get_option('tests') + subdir('tests') +endif diff --git a/src/compiler/meson_options.txt b/src/compiler/meson_options.txt new file mode 100644 index 0000000..c849cea --- /dev/null +++ b/src/compiler/meson_options.txt @@ -0,0 +1 @@ +option('tests', type: 'boolean', value: false, description: 'Build compiler unit tests') diff --git a/src/compiler/subprojects/approvaltests.wrap b/src/compiler/subprojects/approvaltests.wrap new file mode 100644 index 0000000..13e345a --- /dev/null +++ b/src/compiler/subprojects/approvaltests.wrap @@ -0,0 +1,9 @@ +[wrap-git] +url = https://github.com/approvals/ApprovalTests.cpp.git +revision = v.10.13.0 +depth = 1 +method = meson +patch_directory = approvaltests + +[provide] +approvaltests = approvaltests_dep diff --git a/src/compiler/subprojects/packagefiles/approvaltests/meson.build b/src/compiler/subprojects/packagefiles/approvaltests/meson.build new file mode 100644 index 0000000..68ed4d4 --- /dev/null +++ b/src/compiler/subprojects/packagefiles/approvaltests/meson.build @@ -0,0 +1,31 @@ +project( + 'approvaltests', + 'cpp', + version: '10.13.0', +) + +approvaltests_sources = run_command( + 'find', + 'ApprovalTests', + '-name', + '*.cpp', + check: true, +).stdout().strip().split('\n') + +approvaltests_inc = [ + include_directories('.'), + include_directories('ApprovalTests'), +] + +approvaltests_lib = static_library( + 'approvaltests', + approvaltests_sources, + include_directories: approvaltests_inc, +) + +approvaltests_dep = declare_dependency( + include_directories: approvaltests_inc, + link_with: approvaltests_lib, +) + +meson.override_dependency('approvaltests', approvaltests_dep) diff --git a/src/compiler/tests/README.md b/src/compiler/tests/README.md new file mode 100644 index 0000000..db9d6b7 --- /dev/null +++ b/src/compiler/tests/README.md @@ -0,0 +1,30 @@ +# Compiler Tests + +Compiler tests are disabled by default. Golden tests use ApprovalTests.cpp for +approved/received output comparison, and Meson runs one fixture per test. + +To build and run the tests: + +```sh +cd src/compiler +# Or any other C++23 compiler +CXX=g++-13 meson setup build-tests -Dtests=true +meson compile -j 1 -C build-tests +meson test -C build-tests +``` + +Golden tests are discovered from these fixture directories when the build +directory is configured: + +```text +src/compiler/tests/fixtures/parser/ +src/compiler/tests/fixtures/validate/ +src/compiler/tests/fixtures/compile/ +``` + +Each `.rule` fixture should have a sibling `.approved.txt` file. If you add or +remove a `.rule` fixture, reconfigure the test build: + +```sh +meson setup --reconfigure build-tests +``` diff --git a/src/compiler/tests/fixtures/parser/syntax_error.approved.txt b/src/compiler/tests/fixtures/parser/syntax_error.approved.txt new file mode 100644 index 0000000..4b79e51 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/syntax_error.approved.txt @@ -0,0 +1,5 @@ +fixture: fixtures/parser/syntax_error.rule +parse_status: 1 +stderr: +Parser error: fixtures/parser/syntax_error.rule:3:8: syntax error, unexpected end of file, expecting pnode name + diff --git a/src/compiler/tests/fixtures/parser/syntax_error.rule b/src/compiler/tests/fixtures/parser/syntax_error.rule new file mode 100644 index 0000000..6e46faa --- /dev/null +++ b/src/compiler/tests/fixtures/parser/syntax_error.rule @@ -0,0 +1,3 @@ +VnIn(8, BbEntry, 16) ->(0) OpAdd(INT_ADD, BbEntry) +-- +DELETE diff --git a/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.approved.txt b/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.approved.txt new file mode 100644 index 0000000..f248df6 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.approved.txt @@ -0,0 +1,11 @@ +fixture: fixtures/parser/varnode_pnode_rewrite.rule +parse_status: 0 +stderr: + +ast: +VnIn(8, BbEntry, 16) ->(0) OpAdd(INT_ADD, BbEntry); +OpAdd -> VnOut +-- +VnReplacement(8) ->>(0) OpAdd; +OpInserted(INT_SUB BEFORE OpAdd) ->> VnOut + diff --git a/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.rule b/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.rule new file mode 100644 index 0000000..8170455 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.rule @@ -0,0 +1,5 @@ +VnIn(8, BbEntry, 16) ->(0) OpAdd(INT_ADD, BbEntry); +OpAdd -> VnOut +-- +VnReplacement(8) ->>(0) OpAdd; +OpInserted(INT_SUB BEFORE OpAdd) ->> VnOut diff --git a/src/compiler/tests/fixtures/rulecompile/replace_first_arg.approved.txt b/src/compiler/tests/fixtures/rulecompile/replace_first_arg.approved.txt new file mode 100644 index 0000000..0aec487 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/replace_first_arg.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/rulecompile/replace_first_arg.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 0 +pattern_steps_count: 3 +action_steps_count: 1 + diff --git a/src/compiler/tests/fixtures/rulecompile/replace_first_arg.rule b/src/compiler/tests/fixtures/rulecompile/replace_first_arg.rule new file mode 100644 index 0000000..36f47b0 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/replace_first_arg.rule @@ -0,0 +1,3 @@ +o_tmp -> v1 -> (0) o1(INT_ADD, _) +-- +#4 ->> (0) o1 diff --git a/src/compiler/tests/fixtures/rulecompile/syntax_error.approved.txt b/src/compiler/tests/fixtures/rulecompile/syntax_error.approved.txt new file mode 100644 index 0000000..1421bdf --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/syntax_error.approved.txt @@ -0,0 +1,5 @@ +fixture: fixtures/rulecompile/syntax_error.rule +parse_status: 1 +stderr: +Parser error: fixtures/rulecompile/syntax_error.rule:3:8: syntax error, unexpected end of file, expecting pnode name + diff --git a/src/compiler/tests/fixtures/rulecompile/syntax_error.rule b/src/compiler/tests/fixtures/rulecompile/syntax_error.rule new file mode 100644 index 0000000..6e46faa --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/syntax_error.rule @@ -0,0 +1,3 @@ +VnIn(8, BbEntry, 16) ->(0) OpAdd(INT_ADD, BbEntry) +-- +DELETE diff --git a/src/compiler/tests/fixtures/validate/replace_first_arg.approved.txt b/src/compiler/tests/fixtures/validate/replace_first_arg.approved.txt new file mode 100644 index 0000000..9395149 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/replace_first_arg.approved.txt @@ -0,0 +1,10 @@ +fixture: fixtures/validate/replace_first_arg.rule +parse_status: 0 +stderr: + +validate_status: 0 +generated_user_conditions: + +required_conditions: + + diff --git a/src/compiler/tests/fixtures/validate/replace_first_arg.rule b/src/compiler/tests/fixtures/validate/replace_first_arg.rule new file mode 100644 index 0000000..36f47b0 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/replace_first_arg.rule @@ -0,0 +1,3 @@ +o_tmp -> v1 -> (0) o1(INT_ADD, _) +-- +#4 ->> (0) o1 diff --git a/src/compiler/tests/fixtures/validate/syntax_error.approved.txt b/src/compiler/tests/fixtures/validate/syntax_error.approved.txt new file mode 100644 index 0000000..60ae501 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/syntax_error.approved.txt @@ -0,0 +1,5 @@ +fixture: fixtures/validate/syntax_error.rule +parse_status: 1 +stderr: +Parser error: fixtures/validate/syntax_error.rule:3:8: syntax error, unexpected end of file, expecting pnode name + diff --git a/src/compiler/tests/fixtures/validate/syntax_error.rule b/src/compiler/tests/fixtures/validate/syntax_error.rule new file mode 100644 index 0000000..6e46faa --- /dev/null +++ b/src/compiler/tests/fixtures/validate/syntax_error.rule @@ -0,0 +1,3 @@ +VnIn(8, BbEntry, 16) ->(0) OpAdd(INT_ADD, BbEntry) +-- +DELETE diff --git a/src/compiler/tests/golden_common.cpp b/src/compiler/tests/golden_common.cpp new file mode 100644 index 0000000..355288b --- /dev/null +++ b/src/compiler/tests/golden_common.cpp @@ -0,0 +1,73 @@ +#include "golden_common.hh" + +#include "ApprovalTests.hpp" +#include "ApprovalTests/core/ApprovalNamer.h" + +#include +#include +#include +#include +#include + +namespace golden { + +namespace fs = std::filesystem; + +namespace { + +class FixtureAdjacentNamer : public ApprovalTests::ApprovalNamer { +public: + explicit FixtureAdjacentNamer(fs::path fixturePath) + : outputBase(std::move(fixturePath)) { + outputBase.replace_extension(); + } + + std::string getApprovedFile(std::string extensionWithDot) const override { + return pathFor("approved", extensionWithDot); + } + + std::string getReceivedFile(std::string extensionWithDot) const override { + return pathFor("received", extensionWithDot); + } + +private: + std::string + pathFor(const std::string &kind, const std::string &extensionWithDot) const { + fs::path output = outputBase; + output += "." + kind + extensionWithDot; + return output.string(); + } + + fs::path outputBase; +}; + +} // namespace + +ScopedCerrRedirect::ScopedCerrRedirect(std::ostream &replacement) + : originalBuffer(std::cerr.rdbuf(replacement.rdbuf())) {} + +ScopedCerrRedirect::~ScopedCerrRedirect() { std::cerr.rdbuf(originalBuffer); } + +fs::path displayPath(const fs::path &fixturePath) { + return fs::relative(fixturePath, fs::current_path()); +} + +int verifyFixtureOutput( + const fs::path &fixturePath, const std::string &output +) { + try { + static const ApprovalTests::QuietReporter quietReporter; + ApprovalTests::Approvals::verify( + output, + ApprovalTests::Options() + .withReporter(quietReporter) + .withNamer(std::make_shared(fixturePath)) + ); + return 0; + } catch (const std::exception &ex) { + std::cerr << ex.what() << "\n"; + return 1; + } +} + +} // namespace golden diff --git a/src/compiler/tests/golden_common.hh b/src/compiler/tests/golden_common.hh new file mode 100644 index 0000000..013e684 --- /dev/null +++ b/src/compiler/tests/golden_common.hh @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +namespace golden { + +class ScopedCerrRedirect { +public: + explicit ScopedCerrRedirect(std::ostream &replacement); + ~ScopedCerrRedirect(); + + ScopedCerrRedirect(const ScopedCerrRedirect &) = delete; + ScopedCerrRedirect &operator=(const ScopedCerrRedirect &) = delete; + +private: + std::streambuf *originalBuffer; +}; + +std::filesystem::path displayPath(const std::filesystem::path &fixturePath); +int verifyFixtureOutput( + const std::filesystem::path &fixturePath, const std::string &output +); + +} // namespace golden diff --git a/src/compiler/tests/meson.build b/src/compiler/tests/meson.build new file mode 100644 index 0000000..9d54a40 --- /dev/null +++ b/src/compiler/tests/meson.build @@ -0,0 +1,81 @@ +approvaltests_dep = dependency( + 'approvaltests', + fallback: ['approvaltests', 'approvaltests_dep'], +) + +golden_common_src = ['golden_common.cpp'] + +parser_golden_test = executable( + 'parser_golden_test', + golden_common_src + [ + 'parser_golden_test.cpp', + ], + include_directories: [ + inc, + ], + dependencies: [ + parser_lib_dep, + approvaltests_dep, + ], +) + +validate_golden_test = executable( + 'validate_golden_test', + golden_common_src + [ + 'validate_golden_test.cpp', + ], + include_directories: [ + inc, + ], + dependencies: [ + parser_lib_dep, + validator_lib_dep, + approvaltests_dep, + ], +) + +rulecompile_golden_test = executable( + 'rulecompile_golden_test', + golden_common_src + [ + 'rulecompile_golden_test.cpp', + ], + include_directories: [ + inc, + ], + dependencies: [ + parser_lib_dep, + validator_lib_dep, + rulecompile_lib_dep, + approvaltests_dep, + ], +) + +golden_tests = { + 'parser': parser_golden_test, + 'validate': validate_golden_test, + 'rulecompile': rulecompile_golden_test, +} + +foreach stage, runner : golden_tests + fixtures_find = run_command( + 'find', + 'fixtures' / stage, + '-type', + 'f', + '-name', + '*.rule', + check: true, + ) + + fixtures = fixtures_find.stdout().strip().split('\n') + + foreach fixture : fixtures + fixture_name = stage + ' / ' + fixture.split('/')[-1] + test( + fixture_name, + runner, + args: [fixture], + workdir: meson.current_source_dir(), + ) + endforeach +endforeach diff --git a/src/compiler/tests/parser_golden_test.cpp b/src/compiler/tests/parser_golden_test.cpp new file mode 100644 index 0000000..f36a40d --- /dev/null +++ b/src/compiler/tests/parser_golden_test.cpp @@ -0,0 +1,51 @@ +#include "golden_common.hh" +#include "parse/ast_print.hh" +#include "parse/driver.hh" + +#include +#include +#include +#include + +namespace { + +namespace fs = std::filesystem; + +std::string renderFixture(const fs::path &fixturePath) { + std::ostringstream errors; + yy::Driver driver; + + int parseStatus = 0; + { + golden::ScopedCerrRedirect redirect(errors); + parseStatus = driver.parse(fixturePath); + } + + std::ostringstream output; + output << "fixture: " << golden::displayPath(fixturePath).string() << "\n"; + output << "parse_status: " << parseStatus << "\n"; + output << "stderr:\n"; + + const std::string errorText = errors.str(); + output << (errorText.empty() ? "\n" : errorText); + + if (parseStatus == 0) { + output << "ast:\n"; + ast::print::rule(output, driver.getParsedRule()); + output << "\n"; + } + + return output.str(); +} + +} // namespace + +int main(int argc, char **argv) { + if (argc != 2) { + std::cerr << "usage: " << argv[0] << " \n"; + return 2; + } + + const fs::path fixturePath = argv[1]; + return golden::verifyFixtureOutput(fixturePath, renderFixture(fixturePath)); +} diff --git a/src/compiler/tests/rulecompile_golden_test.cpp b/src/compiler/tests/rulecompile_golden_test.cpp new file mode 100644 index 0000000..87d2b9c --- /dev/null +++ b/src/compiler/tests/rulecompile_golden_test.cpp @@ -0,0 +1,90 @@ +#include "compiled_rule.hh" +#include "golden_common.hh" +#include "parse/driver.hh" +#include "rulecompile/rulecompile_driver.hh" +#include "validate/validate_driver.hh" + +#include +#include +#include +#include +#include + +namespace { + +namespace fs = std::filesystem; +namespace compiled = pcodeweaver::compiled; + +void printCompiledRule(std::ostream &out, const compiled::Rule &rule) { + out << "pattern_steps_count: " << rule.pattern.steps.size() << "\n"; + out << "action_steps_count: " << rule.action.steps.size() << "\n"; +} + +std::string renderFixture(const fs::path &fixturePath) { + std::ostringstream errors; + yy::Driver parseDriver; + + int parseStatus = 0; + { + golden::ScopedCerrRedirect redirect(errors); + parseStatus = parseDriver.parse(fixturePath); + } + + std::ostringstream output; + output << "fixture: " << golden::displayPath(fixturePath).string() << "\n"; + output << "parse_status: " << parseStatus << "\n"; + output << "stderr:\n"; + + const std::string errorText = errors.str(); + output << (errorText.empty() ? "\n" : errorText); + + if (parseStatus != 0) { + return output.str(); + } + + const ast::Rule &rule = parseDriver.getParsedRule(); + ValidateDriver validateDriver(parseDriver.getContext()); + auto validateRes = validateDriver.validate(rule); + + output << "validate_status: " << (validateRes.has_value() ? 0 : 1) << "\n"; + if (!validateRes.has_value()) { + output << "validate_error: " << validateRes.error().message() << "\n"; + return output.str(); + } + + std::vector runtimeChecks = + validateDriver.getRuntimeCheckConditions(); + RuleCompileDriver compileDriver( + RuleCompileInput{ + .actions = rule.actions, + .patternGraph = validateDriver.getPGraph(), + .actionGraph = validateDriver.getActGraph(), + .sizeSolver = validateDriver.getSizeSolver(), + .runtimeChecks = runtimeChecks, + .runtimeValueRequirements = + validateDriver.getRuntimeValueRequirements(), + } + ); + + auto compileRes = compileDriver.compile(); + output << "compile_status: " << (compileRes.has_value() ? 0 : 1) << "\n"; + if (!compileRes.has_value()) { + output << "compile_error: " << compileRes.error().message() << "\n"; + return output.str(); + } + + printCompiledRule(output, compileRes.value()); + return output.str(); +} + +} // namespace + +int main(int argc, char **argv) { + if (argc != 2) { + std::cerr << "usage: " << argv[0] << " \n"; + return 2; + } + + const fs::path fixturePath = argv[1]; + return golden::verifyFixtureOutput(fixturePath, renderFixture(fixturePath)); +} diff --git a/src/compiler/tests/validate_golden_test.cpp b/src/compiler/tests/validate_golden_test.cpp new file mode 100644 index 0000000..bc57252 --- /dev/null +++ b/src/compiler/tests/validate_golden_test.cpp @@ -0,0 +1,80 @@ +#include "golden_common.hh" +#include "parse/driver.hh" +#include "validate/validate_driver.hh" + +#include +#include +#include +#include +#include + +namespace { + +namespace fs = std::filesystem; + +void printConditionList( + std::ostream &out, const std::string &label, + const std::vector &conditions +) { + out << label << ":\n"; + if (conditions.empty()) { + out << " \n"; + return; + } + + for (const speccond::SpecCondition &condition : conditions) { + out << " " << condition << "\n"; + } +} + +std::string renderFixture(const fs::path &fixturePath) { + std::ostringstream errors; + yy::Driver parseDriver; + + int parseStatus = 0; + { + golden::ScopedCerrRedirect redirect(errors); + parseStatus = parseDriver.parse(fixturePath); + } + + std::ostringstream output; + output << "fixture: " << golden::displayPath(fixturePath).string() << "\n"; + output << "parse_status: " << parseStatus << "\n"; + output << "stderr:\n"; + + const std::string errorText = errors.str(); + output << (errorText.empty() ? "\n" : errorText); + + if (parseStatus != 0) { + return output.str(); + } + + ValidateDriver validateDriver(parseDriver.getContext()); + const Errorable validateRes = + validateDriver.validate(parseDriver.getParsedRule()); + + output << "validate_status: " << (validateRes.has_value() ? 0 : 1) << "\n"; + if (!validateRes.has_value()) { + output << "validate_error: " << validateRes.error().message() << "\n"; + return output.str(); + } + + printConditionList( + output, "generated_user_conditions", validateDriver.getURTC() + ); + printConditionList(output, "required_conditions", validateDriver.getRQC()); + + return output.str(); +} + +} // namespace + +int main(int argc, char **argv) { + if (argc != 2) { + std::cerr << "usage: " << argv[0] << " \n"; + return 2; + } + + const fs::path fixturePath = argv[1]; + return golden::verifyFixtureOutput(fixturePath, renderFixture(fixturePath)); +} From 30f59b6bf742a21c0b644dc3e90084dcb6f4525a Mon Sep 17 00:00:00 2001 From: Osogi Date: Fri, 29 May 2026 04:18:59 +0300 Subject: [PATCH 2/9] parse: fix rebuild error --- src/compiler/parse/context.hh | 2 +- src/compiler/parse/driver.hh | 2 +- src/compiler/parse/op_type_predefined.cpp | 2 +- src/compiler/parse/parser.yy | 4 ++-- src/compiler/parse/scanner.hh | 2 +- src/compiler/parse/scanner.ll | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/compiler/parse/context.hh b/src/compiler/parse/context.hh index 24ade91..199c425 100644 --- a/src/compiler/parse/context.hh +++ b/src/compiler/parse/context.hh @@ -7,7 +7,7 @@ #include "parse/op_type_predefined.hh" // generated headers -#include "parse/parser.hh" +#include "parse/parser.hpp" struct Context { Context() diff --git a/src/compiler/parse/driver.hh b/src/compiler/parse/driver.hh index b713773..eef7837 100644 --- a/src/compiler/parse/driver.hh +++ b/src/compiler/parse/driver.hh @@ -8,7 +8,7 @@ #include "parse/scanner.hh" // generated headers -#include "parse/parser.hh" +#include "parse/parser.hpp" #include diff --git a/src/compiler/parse/op_type_predefined.cpp b/src/compiler/parse/op_type_predefined.cpp index a7b72b2..0d6a5c3 100644 --- a/src/compiler/parse/op_type_predefined.cpp +++ b/src/compiler/parse/op_type_predefined.cpp @@ -4,7 +4,7 @@ #include "parse/op_type_predefined.hh" // generated headers -#include "parse/parser.hh" +#include "parse/parser.hpp" #include #include diff --git a/src/compiler/parse/parser.yy b/src/compiler/parse/parser.yy index 0e65a46..5467017 100644 --- a/src/compiler/parse/parser.yy +++ b/src/compiler/parse/parser.yy @@ -8,7 +8,7 @@ %skeleton "lalr1.cc" %require "3.8" -%defines "parse/parser.hh" +%defines "parse/parser.hpp" %define api.parser.class { Parser } %define api.token.constructor @@ -37,7 +37,7 @@ #include "parse/driver.hh" #include "parse/scanner.hh" - #include "parse/parser.hh" + #include "parse/parser.hpp" static yy::Parser::symbol_type yylex(yy::Scanner &scanner) { return scanner.get_next_token(); diff --git a/src/compiler/parse/scanner.hh b/src/compiler/parse/scanner.hh index 8057d7a..26ebe9c 100644 --- a/src/compiler/parse/scanner.hh +++ b/src/compiler/parse/scanner.hh @@ -8,7 +8,7 @@ #pragma once // generated headers -#include "parse/parser.hh" +#include "parse/parser.hpp" #undef yyFlexLexer #include diff --git a/src/compiler/parse/scanner.ll b/src/compiler/parse/scanner.ll index cff3570..37029f3 100644 --- a/src/compiler/parse/scanner.ll +++ b/src/compiler/parse/scanner.ll @@ -17,7 +17,7 @@ #include "parse/driver.hh" #include "parse/scanner.hh" - #include "parse/parser.hh" + #include "parse/parser.hpp" // Original yyterminate() macro returns int. Since we're using Bison 3 variants // as tokens, we must redefine it to change type from `int` to `Parser::semantic_type` From 80bb1f448fa963652f290ce513c18caae567e823 Mon Sep 17 00:00:00 2001 From: Osogi Date: Fri, 29 May 2026 05:21:21 +0300 Subject: [PATCH 3/9] tests: add parser tests --- .../fixtures/parser/copy_propagation.approved.txt | 9 +++++++++ .../tests/fixtures/parser/copy_propagation.rule | 3 +++ .../fixtures/parser/empty_examples.approved.txt | 9 +++++++++ .../tests/fixtures/parser/empty_examples.rule | 3 +++ .../parser/invalid_arrow_action.approved.txt | 5 +++++ .../fixtures/parser/invalid_arrow_action.rule | 3 +++ .../parser/invalid_arrow_pattern copy.approved.txt | 5 +++++ .../parser/invalid_arrow_pattern copy.rule | 3 +++ .../invalid_missing_action_separator.approved.txt | 5 +++++ .../parser/invalid_missing_action_separator.rule | 2 ++ ...invalid_trailing_pattern_separator.approved.txt | 5 +++++ .../parser/invalid_trailing_pattern_separator.rule | 3 +++ .../parser/invalid_unknown_opcode.approved.txt | 5 +++++ .../fixtures/parser/invalid_unknown_opcode.rule | 3 +++ .../parser/invalid_varnode_as_pnode.approved.txt | 5 +++++ .../fixtures/parser/invalid_varnode_as_pnode.rule | 4 ++++ .../fixtures/parser/syntax_error.approved.txt | 5 ----- .../tests/fixtures/parser/syntax_error.rule | 3 --- .../parser/typed_terms_and_cfg.approved.txt | 14 ++++++++++++++ .../tests/fixtures/parser/typed_terms_and_cfg.rule | 8 ++++++++ .../fixtures/parser/varnode_offset.approved.txt | 9 +++++++++ .../tests/fixtures/parser/varnode_offset.rule | 3 +++ .../parser/varnode_pnode_rewrite.approved.txt | 11 ----------- .../fixtures/parser/varnode_pnode_rewrite.rule | 5 ----- 24 files changed, 106 insertions(+), 24 deletions(-) create mode 100644 src/compiler/tests/fixtures/parser/copy_propagation.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/copy_propagation.rule create mode 100644 src/compiler/tests/fixtures/parser/empty_examples.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/empty_examples.rule create mode 100644 src/compiler/tests/fixtures/parser/invalid_arrow_action.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/invalid_arrow_action.rule create mode 100644 src/compiler/tests/fixtures/parser/invalid_arrow_pattern copy.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/invalid_arrow_pattern copy.rule create mode 100644 src/compiler/tests/fixtures/parser/invalid_missing_action_separator.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/invalid_missing_action_separator.rule create mode 100644 src/compiler/tests/fixtures/parser/invalid_trailing_pattern_separator.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/invalid_trailing_pattern_separator.rule create mode 100644 src/compiler/tests/fixtures/parser/invalid_unknown_opcode.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/invalid_unknown_opcode.rule create mode 100644 src/compiler/tests/fixtures/parser/invalid_varnode_as_pnode.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/invalid_varnode_as_pnode.rule delete mode 100644 src/compiler/tests/fixtures/parser/syntax_error.approved.txt delete mode 100644 src/compiler/tests/fixtures/parser/syntax_error.rule create mode 100644 src/compiler/tests/fixtures/parser/typed_terms_and_cfg.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/typed_terms_and_cfg.rule create mode 100644 src/compiler/tests/fixtures/parser/varnode_offset.approved.txt create mode 100644 src/compiler/tests/fixtures/parser/varnode_offset.rule delete mode 100644 src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.approved.txt delete mode 100644 src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.rule diff --git a/src/compiler/tests/fixtures/parser/copy_propagation.approved.txt b/src/compiler/tests/fixtures/parser/copy_propagation.approved.txt new file mode 100644 index 0000000..5519344 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/copy_propagation.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/parser/copy_propagation.rule +parse_status: 0 +stderr: + +ast: +v_orig ->(0) o_copy(COPY, __b_0) -> v_copy ->(0) o_any(ANY, __b_1) +-- +v_orig ->>(0) o_any + diff --git a/src/compiler/tests/fixtures/parser/copy_propagation.rule b/src/compiler/tests/fixtures/parser/copy_propagation.rule new file mode 100644 index 0000000..16cf296 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/copy_propagation.rule @@ -0,0 +1,3 @@ +v_orig -> (0) o_copy(COPY, _) -> v_copy -> (0) o_any(_, _) +-- +v_orig ->> (0) o_any diff --git a/src/compiler/tests/fixtures/parser/empty_examples.approved.txt b/src/compiler/tests/fixtures/parser/empty_examples.approved.txt new file mode 100644 index 0000000..758e022 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/empty_examples.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/parser/empty_examples.rule +parse_status: 0 +stderr: + +ast: +VEMPTY ->(0) OPEMPTY -> VEMPTY +-- +VEMPTY ->>(0) op_new + diff --git a/src/compiler/tests/fixtures/parser/empty_examples.rule b/src/compiler/tests/fixtures/parser/empty_examples.rule new file mode 100644 index 0000000..988bebe --- /dev/null +++ b/src/compiler/tests/fixtures/parser/empty_examples.rule @@ -0,0 +1,3 @@ +VEMPTY -> (0) OPEMPTY -> VEMPTY +-- +VEMPTY ->>(0) op_new \ No newline at end of file diff --git a/src/compiler/tests/fixtures/parser/invalid_arrow_action.approved.txt b/src/compiler/tests/fixtures/parser/invalid_arrow_action.approved.txt new file mode 100644 index 0000000..978b068 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_arrow_action.approved.txt @@ -0,0 +1,5 @@ +fixture: fixtures/parser/invalid_arrow_action.rule +parse_status: 1 +stderr: +Parser error: fixtures/parser/invalid_arrow_action.rule:3:4: syntax error, unexpected ->, expecting end of file + diff --git a/src/compiler/tests/fixtures/parser/invalid_arrow_action.rule b/src/compiler/tests/fixtures/parser/invalid_arrow_action.rule new file mode 100644 index 0000000..822d2f5 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_arrow_action.rule @@ -0,0 +1,3 @@ +v1 -> (0) op(INT_ADD, _) +-- +v1 -> (0) op diff --git a/src/compiler/tests/fixtures/parser/invalid_arrow_pattern copy.approved.txt b/src/compiler/tests/fixtures/parser/invalid_arrow_pattern copy.approved.txt new file mode 100644 index 0000000..4479b6d --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_arrow_pattern copy.approved.txt @@ -0,0 +1,5 @@ +fixture: fixtures/parser/invalid_arrow_pattern copy.rule +parse_status: 1 +stderr: +Parser error: fixtures/parser/invalid_arrow_pattern copy.rule:1:4: syntax error, unexpected ->>, expecting -- or ; + diff --git a/src/compiler/tests/fixtures/parser/invalid_arrow_pattern copy.rule b/src/compiler/tests/fixtures/parser/invalid_arrow_pattern copy.rule new file mode 100644 index 0000000..a9d32ec --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_arrow_pattern copy.rule @@ -0,0 +1,3 @@ +v1 ->> (0) op(INT_ADD, _) +-- +v1 ->> (0) op diff --git a/src/compiler/tests/fixtures/parser/invalid_missing_action_separator.approved.txt b/src/compiler/tests/fixtures/parser/invalid_missing_action_separator.approved.txt new file mode 100644 index 0000000..a7376ed --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_missing_action_separator.approved.txt @@ -0,0 +1,5 @@ +fixture: fixtures/parser/invalid_missing_action_separator.rule +parse_status: 1 +stderr: +Parser error: fixtures/parser/invalid_missing_action_separator.rule:2:1: syntax error, unexpected varnode name, expecting -- or ; + diff --git a/src/compiler/tests/fixtures/parser/invalid_missing_action_separator.rule b/src/compiler/tests/fixtures/parser/invalid_missing_action_separator.rule new file mode 100644 index 0000000..9dc4bcd --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_missing_action_separator.rule @@ -0,0 +1,2 @@ +v_orig -> (0) o_copy(COPY, _) +v_orig ->> (0) o_copy diff --git a/src/compiler/tests/fixtures/parser/invalid_trailing_pattern_separator.approved.txt b/src/compiler/tests/fixtures/parser/invalid_trailing_pattern_separator.approved.txt new file mode 100644 index 0000000..ef7f1b0 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_trailing_pattern_separator.approved.txt @@ -0,0 +1,5 @@ +fixture: fixtures/parser/invalid_trailing_pattern_separator.rule +parse_status: 1 +stderr: +Parser error: fixtures/parser/invalid_trailing_pattern_separator.rule:2:1: syntax error, unexpected -- + diff --git a/src/compiler/tests/fixtures/parser/invalid_trailing_pattern_separator.rule b/src/compiler/tests/fixtures/parser/invalid_trailing_pattern_separator.rule new file mode 100644 index 0000000..1d5e9a9 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_trailing_pattern_separator.rule @@ -0,0 +1,3 @@ +v_orig; +-- +v_orig diff --git a/src/compiler/tests/fixtures/parser/invalid_unknown_opcode.approved.txt b/src/compiler/tests/fixtures/parser/invalid_unknown_opcode.approved.txt new file mode 100644 index 0000000..001d8a7 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_unknown_opcode.approved.txt @@ -0,0 +1,5 @@ +fixture: fixtures/parser/invalid_unknown_opcode.rule +parse_status: 1 +stderr: +Parser error: fixtures/parser/invalid_unknown_opcode.rule:1:7: syntax error, unexpected variable name + diff --git a/src/compiler/tests/fixtures/parser/invalid_unknown_opcode.rule b/src/compiler/tests/fixtures/parser/invalid_unknown_opcode.rule new file mode 100644 index 0000000..7b4b062 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_unknown_opcode.rule @@ -0,0 +1,3 @@ +o_bad(INT_UNKNOWN, _) +-- +DELETE o_bad diff --git a/src/compiler/tests/fixtures/parser/invalid_varnode_as_pnode.approved.txt b/src/compiler/tests/fixtures/parser/invalid_varnode_as_pnode.approved.txt new file mode 100644 index 0000000..3b97ad0 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_varnode_as_pnode.approved.txt @@ -0,0 +1,5 @@ +fixture: fixtures/parser/invalid_varnode_as_pnode.rule +parse_status: 1 +stderr: +Parser error: fixtures/parser/invalid_varnode_as_pnode.rule:2:11: syntax error, unexpected varnode name, expecting OPEMPTY or pnode name + diff --git a/src/compiler/tests/fixtures/parser/invalid_varnode_as_pnode.rule b/src/compiler/tests/fixtures/parser/invalid_varnode_as_pnode.rule new file mode 100644 index 0000000..adea23c --- /dev/null +++ b/src/compiler/tests/fixtures/parser/invalid_varnode_as_pnode.rule @@ -0,0 +1,4 @@ +v2 -> (0) op; +v1 -> (0) v2 +-- +v1 -> (0) op diff --git a/src/compiler/tests/fixtures/parser/syntax_error.approved.txt b/src/compiler/tests/fixtures/parser/syntax_error.approved.txt deleted file mode 100644 index 4b79e51..0000000 --- a/src/compiler/tests/fixtures/parser/syntax_error.approved.txt +++ /dev/null @@ -1,5 +0,0 @@ -fixture: fixtures/parser/syntax_error.rule -parse_status: 1 -stderr: -Parser error: fixtures/parser/syntax_error.rule:3:8: syntax error, unexpected end of file, expecting pnode name - diff --git a/src/compiler/tests/fixtures/parser/syntax_error.rule b/src/compiler/tests/fixtures/parser/syntax_error.rule deleted file mode 100644 index 6e46faa..0000000 --- a/src/compiler/tests/fixtures/parser/syntax_error.rule +++ /dev/null @@ -1,3 +0,0 @@ -VnIn(8, BbEntry, 16) ->(0) OpAdd(INT_ADD, BbEntry) --- -DELETE diff --git a/src/compiler/tests/fixtures/parser/typed_terms_and_cfg.approved.txt b/src/compiler/tests/fixtures/parser/typed_terms_and_cfg.approved.txt new file mode 100644 index 0000000..b48aecc --- /dev/null +++ b/src/compiler/tests/fixtures/parser/typed_terms_and_cfg.approved.txt @@ -0,0 +1,14 @@ +fixture: fixtures/parser/typed_terms_and_cfg.rule +parse_status: 0 +stderr: + +ast: +o_add(INT_ADD, bb_entry) -> v_sum(8, bb_entry, 16); +bb_entry ->(0) bb_next; +bb_entry <= bb_next +-- +o_new(INT_MULT BEFORE o_add); +#42 ->>(1) o_new; +o_new ->> v_sum; +DELETE o_add + diff --git a/src/compiler/tests/fixtures/parser/typed_terms_and_cfg.rule b/src/compiler/tests/fixtures/parser/typed_terms_and_cfg.rule new file mode 100644 index 0000000..59ade0a --- /dev/null +++ b/src/compiler/tests/fixtures/parser/typed_terms_and_cfg.rule @@ -0,0 +1,8 @@ +o_add(INT_ADD, bb_entry) -> v_sum(8, bb_entry, 16); +bb_entry -> (0) bb_next; +bb_entry <= bb_next +-- +o_new(INT_MULT BEFORE o_add); +#42 ->> (1) o_new; +o_new ->> v_sum; +DELETE o_add diff --git a/src/compiler/tests/fixtures/parser/varnode_offset.approved.txt b/src/compiler/tests/fixtures/parser/varnode_offset.approved.txt new file mode 100644 index 0000000..92fb61d --- /dev/null +++ b/src/compiler/tests/fixtures/parser/varnode_offset.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/parser/varnode_offset.rule +parse_status: 0 +stderr: + +ast: +v1(__s_0, __b_0, 16) ->(0) op(INT_ADD, __b_1) +-- +v1 ->>(0) op + diff --git a/src/compiler/tests/fixtures/parser/varnode_offset.rule b/src/compiler/tests/fixtures/parser/varnode_offset.rule new file mode 100644 index 0000000..41ea986 --- /dev/null +++ b/src/compiler/tests/fixtures/parser/varnode_offset.rule @@ -0,0 +1,3 @@ +v1(_, _, 16) -> (0) op(INT_ADD, _) +-- +v1 ->> (0) op diff --git a/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.approved.txt b/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.approved.txt deleted file mode 100644 index f248df6..0000000 --- a/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.approved.txt +++ /dev/null @@ -1,11 +0,0 @@ -fixture: fixtures/parser/varnode_pnode_rewrite.rule -parse_status: 0 -stderr: - -ast: -VnIn(8, BbEntry, 16) ->(0) OpAdd(INT_ADD, BbEntry); -OpAdd -> VnOut --- -VnReplacement(8) ->>(0) OpAdd; -OpInserted(INT_SUB BEFORE OpAdd) ->> VnOut - diff --git a/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.rule b/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.rule deleted file mode 100644 index 8170455..0000000 --- a/src/compiler/tests/fixtures/parser/varnode_pnode_rewrite.rule +++ /dev/null @@ -1,5 +0,0 @@ -VnIn(8, BbEntry, 16) ->(0) OpAdd(INT_ADD, BbEntry); -OpAdd -> VnOut --- -VnReplacement(8) ->>(0) OpAdd; -OpInserted(INT_SUB BEFORE OpAdd) ->> VnOut From c23128d195dea2543e517e72a81e57760e1aa706 Mon Sep 17 00:00:00 2001 From: Osogi Date: Fri, 29 May 2026 19:00:37 +0300 Subject: [PATCH 4/9] validate: fix ghostnode and implicit pnode without type changing errors --- src/compiler/validate/action_pcodegraph.cpp | 68 ++++++++++++++++++--- src/compiler/validate/action_pcodegraph.hh | 10 +++ 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/src/compiler/validate/action_pcodegraph.cpp b/src/compiler/validate/action_pcodegraph.cpp index bcdcb87..8823833 100644 --- a/src/compiler/validate/action_pcodegraph.cpp +++ b/src/compiler/validate/action_pcodegraph.cpp @@ -12,13 +12,28 @@ ActionPcodeGraph::ActionPcodeGraph(const PcodeGraph &base) : PcodeGraph(base), patternVarnodeDefEmpty() { for (const auto &[_id, gv] : liveVarnodes()) { const VarGraphNode *node = get_if_uniq(gv); - if (node == nullptr || node->isGhost || !node->edges.def.has_value()) { + if (node == nullptr || !node->edges.def.has_value()) { continue; } patternVarnodeDefEmpty.emplace( node->id, node->edges.def.value() == nullptr ); } + + for (const auto &[id, gp] : livePnodes()) { + const OpGraphNode &node = *unpackGP(*gp); + if (node.isGhost || node.opTp.has_value()) { + continue; + } + + patternPnodeConnectionsWithoutType.emplace( + id, + PatternPnodeConnections{ + .inrefs = node.edges.inrefs, + .output = node.edges.output, + } + ); + } } Errorable NewOpGraphNode::addSpec(const ast::PnodeSpecTypeAndLoc &spec) { @@ -99,13 +114,6 @@ ActionPcodeGraph::validateExistingPnodeActionTarget(GraphPnode *gp) { return gp; } - if (!og.opTp.has_value()) { - return err( - "Action cannot operate on pnode " + og.id.getName() + - " because its operation type is undefined" - ); - } - return gp; } @@ -386,6 +394,45 @@ Errorable ActionPcodeGraph::validateExistingVarnodeDefStability( ); } +Errorable ActionPcodeGraph::validateExistingPnodeWithoutTypeStability( + const OpGraphNode &node +) { + auto original = patternPnodeConnectionsWithoutType.find(node.id); + if (original == patternPnodeConnectionsWithoutType.end()) { + return {}; + } + + if (node.edges.output != original->second.output || + node.edges.inrefs != original->second.inrefs) { + return err( + "Action cannot change connections for pnode " + node.id.getName() + + " because its operation type is undefined" + ); + } + + return {}; +} + +Errorable ActionPcodeGraph::validateExistingPnodesWithoutTypeStability() { + for (const auto &[id, _connections] : patternPnodeConnectionsWithoutType) { + auto it = pnodes.find(id); + if (it == pnodes.end() || isDeleted(*it->second)) { + return err( + "Action cannot delete pnode " + id.getName() + + " because its operation type is undefined" + ); + } + + auto res = + validateExistingPnodeWithoutTypeStability(*unpackGP(*it->second)); + if (!res.has_value()) { + return res; + } + } + + return {}; +} + Errorable ActionPcodeGraph::validateNewPnode(const NewOpGraphNode &node) { if (!node.opTp.has_value()) { return err( @@ -420,6 +467,11 @@ Errorable ActionPcodeGraph::validate() { } } + res = validateExistingPnodesWithoutTypeStability(); + if (!res.has_value()) { + return res; + } + for (const auto &[_id, newVarnode] : newVarnodes) { auto res = validateNewVarnode(*newVarnode); if (!res.has_value()) { diff --git a/src/compiler/validate/action_pcodegraph.hh b/src/compiler/validate/action_pcodegraph.hh index b133235..6f57d7c 100644 --- a/src/compiler/validate/action_pcodegraph.hh +++ b/src/compiler/validate/action_pcodegraph.hh @@ -44,6 +44,9 @@ protected: Errorable addEmptyAction(const ast::EmptyAction &ea); Errorable addAction(const ast::RuleAction &act); Errorable validateExistingVarnodeDefStability(const VarGraphNode &node); + Errorable + validateExistingPnodeWithoutTypeStability(const OpGraphNode &node); + Errorable validateExistingPnodesWithoutTypeStability(); Errorable validateNewVarnode(const NewVarGraphNode &node); Errorable validateNewPnode(const NewOpGraphNode &node); @@ -64,7 +67,14 @@ public: std::vector getNewPnodeIds() const; protected: + struct PatternPnodeConnections { + std::unordered_map inrefs; + GraphVarnode *output; + }; + std::unordered_map patternVarnodeDefEmpty; + std::unordered_map + patternPnodeConnectionsWithoutType; std::unordered_map newVarnodes; From 57ad4e5f2cdbf5763da0ae3e56b61b8bfc8d9dc4 Mon Sep 17 00:00:00 2001 From: Osogi Date: Fri, 29 May 2026 18:02:44 +0300 Subject: [PATCH 5/9] tests: add validate tests --- .../act_inv_implicit_op_change.approved.txt | 7 ++++ .../validate/act_inv_implicit_op_change.rule | 6 ++++ .../act_inv_op_without_type.approved.txt | 7 ++++ .../validate/act_inv_op_without_type.rule | 4 +++ .../validate/act_inv_trans_inf.approved.txt | 7 ++++ .../fixtures/validate/act_inv_trans_inf.rule | 4 +++ .../act_inv_varnode_explicit_def.approved.txt | 7 ++++ .../act_inv_varnode_explicit_def.rule | 5 +++ .../act_inv_varnode_no_def.approved.txt | 7 ++++ .../validate/act_inv_varnode_no_def.rule | 6 ++++ ..._inv_varnode_no_def_ghostnode.approved.txt | 7 ++++ .../act_inv_varnode_no_def_ghostnode.rule | 6 ++++ ...roved.txt => act_op_any_type.approved.txt} | 2 +- .../fixtures/validate/act_op_any_type.rule | 4 +++ .../fixtures/validate/big_rule.approved.txt | 12 +++++++ .../tests/fixtures/validate/big_rule.rule | 35 +++++++++++++++++++ .../fixtures/validate/conds_dom.approved.txt | 12 +++++++ .../tests/fixtures/validate/conds_dom.rule | 5 +++ .../validate/conds_trans_dom.approved.txt | 10 ++++++ .../fixtures/validate/conds_trans_dom.rule | 3 ++ .../ghost_nodes_rewritte_type.approved.txt | 10 ++++++ .../validate/ghost_nodes_rewritte_type.rule | 5 +++ .../ghost_nodes_save_type.approved.txt | 7 ++++ .../validate/ghost_nodes_save_type.rule | 3 ++ .../fixtures/validate/new_pnode.approved.txt | 10 ++++++ .../tests/fixtures/validate/new_pnode.rule | 4 +++ .../new_pnode_bad_struct.approved.txt | 7 ++++ .../validate/new_pnode_bad_struct.rule | 3 ++ .../validate/new_pnode_no_spec.approved.txt | 7 ++++ .../fixtures/validate/new_pnode_no_spec.rule | 3 ++ .../validate/new_varnode.approved.txt | 10 ++++++ .../tests/fixtures/validate/new_varnode.rule | 3 ++ .../new_varnode_witohout_spec.approved.txt | 10 ++++++ .../validate/new_varnode_witohout_spec.rule | 3 ++ .../validate/op_delete_invalid.approved.txt | 7 ++++ .../fixtures/validate/op_delete_invalid.rule | 3 ++ .../validate/op_delete_valid.approved.txt | 10 ++++++ .../fixtures/validate/op_delete_valid.rule | 4 +++ .../pat_inv_arg_of_opempty.approved.txt | 7 ++++ .../validate/pat_inv_arg_of_opempty.rule | 3 ++ .../validate/pat_inv_const_def.approved.txt | 7 ++++ .../fixtures/validate/pat_inv_const_def.rule | 3 ++ .../pat_inv_double_def_vnode.approved.txt | 7 ++++ .../validate/pat_inv_double_def_vnode.rule | 4 +++ .../validate/pat_inv_op_type.approved.txt | 7 ++++ .../fixtures/validate/pat_inv_op_type.rule | 3 ++ .../validate/pat_inv_trans_inf.approved.txt | 7 ++++ .../fixtures/validate/pat_inv_trans_inf.rule | 12 +++++++ .../fixtures/validate/replace_first_arg.rule | 3 -- .../fixtures/validate/sanity.approved.txt | 10 ++++++ .../tests/fixtures/validate/sanity.rule | 3 ++ .../validate/syntax_error.approved.txt | 2 +- .../tests/fixtures/validate/syntax_error.rule | 5 ++- 53 files changed, 340 insertions(+), 8 deletions(-) create mode 100644 src/compiler/tests/fixtures/validate/act_inv_implicit_op_change.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/act_inv_implicit_op_change.rule create mode 100644 src/compiler/tests/fixtures/validate/act_inv_op_without_type.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/act_inv_op_without_type.rule create mode 100644 src/compiler/tests/fixtures/validate/act_inv_trans_inf.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/act_inv_trans_inf.rule create mode 100644 src/compiler/tests/fixtures/validate/act_inv_varnode_explicit_def.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/act_inv_varnode_explicit_def.rule create mode 100644 src/compiler/tests/fixtures/validate/act_inv_varnode_no_def.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/act_inv_varnode_no_def.rule create mode 100644 src/compiler/tests/fixtures/validate/act_inv_varnode_no_def_ghostnode.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/act_inv_varnode_no_def_ghostnode.rule rename src/compiler/tests/fixtures/validate/{replace_first_arg.approved.txt => act_op_any_type.approved.txt} (70%) create mode 100644 src/compiler/tests/fixtures/validate/act_op_any_type.rule create mode 100644 src/compiler/tests/fixtures/validate/big_rule.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/big_rule.rule create mode 100644 src/compiler/tests/fixtures/validate/conds_dom.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/conds_dom.rule create mode 100644 src/compiler/tests/fixtures/validate/conds_trans_dom.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/conds_trans_dom.rule create mode 100644 src/compiler/tests/fixtures/validate/ghost_nodes_rewritte_type.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/ghost_nodes_rewritte_type.rule create mode 100644 src/compiler/tests/fixtures/validate/ghost_nodes_save_type.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/ghost_nodes_save_type.rule create mode 100644 src/compiler/tests/fixtures/validate/new_pnode.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/new_pnode.rule create mode 100644 src/compiler/tests/fixtures/validate/new_pnode_bad_struct.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/new_pnode_bad_struct.rule create mode 100644 src/compiler/tests/fixtures/validate/new_pnode_no_spec.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/new_pnode_no_spec.rule create mode 100644 src/compiler/tests/fixtures/validate/new_varnode.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/new_varnode.rule create mode 100644 src/compiler/tests/fixtures/validate/new_varnode_witohout_spec.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/new_varnode_witohout_spec.rule create mode 100644 src/compiler/tests/fixtures/validate/op_delete_invalid.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/op_delete_invalid.rule create mode 100644 src/compiler/tests/fixtures/validate/op_delete_valid.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/op_delete_valid.rule create mode 100644 src/compiler/tests/fixtures/validate/pat_inv_arg_of_opempty.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/pat_inv_arg_of_opempty.rule create mode 100644 src/compiler/tests/fixtures/validate/pat_inv_const_def.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/pat_inv_const_def.rule create mode 100644 src/compiler/tests/fixtures/validate/pat_inv_double_def_vnode.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/pat_inv_double_def_vnode.rule create mode 100644 src/compiler/tests/fixtures/validate/pat_inv_op_type.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/pat_inv_op_type.rule create mode 100644 src/compiler/tests/fixtures/validate/pat_inv_trans_inf.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/pat_inv_trans_inf.rule delete mode 100644 src/compiler/tests/fixtures/validate/replace_first_arg.rule create mode 100644 src/compiler/tests/fixtures/validate/sanity.approved.txt create mode 100644 src/compiler/tests/fixtures/validate/sanity.rule diff --git a/src/compiler/tests/fixtures/validate/act_inv_implicit_op_change.approved.txt b/src/compiler/tests/fixtures/validate/act_inv_implicit_op_change.approved.txt new file mode 100644 index 0000000..5d5c4ea --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_implicit_op_change.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/act_inv_implicit_op_change.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Validate Action Graph: Action cannot change connections for pnode op3 because its operation type is undefined + diff --git a/src/compiler/tests/fixtures/validate/act_inv_implicit_op_change.rule b/src/compiler/tests/fixtures/validate/act_inv_implicit_op_change.rule new file mode 100644 index 0000000..5c670a3 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_implicit_op_change.rule @@ -0,0 +1,6 @@ +v1 -> (0) op1(INT_ADD, _) -> vtmp; + +op3 -> v2 -> (0) op2 +-- +op1 ->> v2; +#1 ->> (0) op_new(COPY AFTER op1) ->> vtmp diff --git a/src/compiler/tests/fixtures/validate/act_inv_op_without_type.approved.txt b/src/compiler/tests/fixtures/validate/act_inv_op_without_type.approved.txt new file mode 100644 index 0000000..8a5d6d4 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_op_without_type.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/act_inv_op_without_type.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Validate Action Graph: Action cannot change connections for pnode op1 because its operation type is undefined + diff --git a/src/compiler/tests/fixtures/validate/act_inv_op_without_type.rule b/src/compiler/tests/fixtures/validate/act_inv_op_without_type.rule new file mode 100644 index 0000000..353904b --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_op_without_type.rule @@ -0,0 +1,4 @@ +v1 -> (0) op1 + +-- +#2 ->> (0) op1 diff --git a/src/compiler/tests/fixtures/validate/act_inv_trans_inf.approved.txt b/src/compiler/tests/fixtures/validate/act_inv_trans_inf.approved.txt new file mode 100644 index 0000000..f951b2c --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_trans_inf.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/act_inv_trans_inf.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Inference Action Graph: Can't unite 8 and 1 + diff --git a/src/compiler/tests/fixtures/validate/act_inv_trans_inf.rule b/src/compiler/tests/fixtures/validate/act_inv_trans_inf.rule new file mode 100644 index 0000000..f0c6c6d --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_trans_inf.rule @@ -0,0 +1,4 @@ +v1(1, _) -> (0) op1(INT_ADD, _) +-- + +#1 ->>(0) op_new(COPY BEFORE op1) ->> v2(8) ->> (1) op1 \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/act_inv_varnode_explicit_def.approved.txt b/src/compiler/tests/fixtures/validate/act_inv_varnode_explicit_def.approved.txt new file mode 100644 index 0000000..1b082b1 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_varnode_explicit_def.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/act_inv_varnode_explicit_def.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Build Action Graph (Action Step): Varnode v2 should has explicit define pnode + diff --git a/src/compiler/tests/fixtures/validate/act_inv_varnode_explicit_def.rule b/src/compiler/tests/fixtures/validate/act_inv_varnode_explicit_def.rule new file mode 100644 index 0000000..d9ca2ce --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_varnode_explicit_def.rule @@ -0,0 +1,5 @@ +v1 -> (0) op1(INT_ADD, _); + +v2 -> (0) op2 +-- +op1 ->> v2 diff --git a/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def.approved.txt b/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def.approved.txt new file mode 100644 index 0000000..9c8059e --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/act_inv_varnode_no_def.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Validate Action Graph: Action cannot change whether varnode vtmp is defined by EMPTY pnode + diff --git a/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def.rule b/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def.rule new file mode 100644 index 0000000..af0b65a --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def.rule @@ -0,0 +1,6 @@ +v1 -> (0) op1(INT_ADD, _) -> vtmp; + +op3(INT_AND, _) -> v2 -> (0) op2 +-- +op1 ->> v2; +op3 ->> v_new \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def_ghostnode.approved.txt b/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def_ghostnode.approved.txt new file mode 100644 index 0000000..223124e --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def_ghostnode.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/act_inv_varnode_no_def_ghostnode.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Validate Action Graph: Action cannot change whether varnode _ghost_out_of_op1 is defined by EMPTY pnode + diff --git a/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def_ghostnode.rule b/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def_ghostnode.rule new file mode 100644 index 0000000..04b05e2 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_inv_varnode_no_def_ghostnode.rule @@ -0,0 +1,6 @@ +v1 -> (0) op1(INT_ADD, _); + +op3(INT_AND, _) -> v2 -> (0) op2 +-- +op1 ->> v2; +op3 ->> v_new \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/replace_first_arg.approved.txt b/src/compiler/tests/fixtures/validate/act_op_any_type.approved.txt similarity index 70% rename from src/compiler/tests/fixtures/validate/replace_first_arg.approved.txt rename to src/compiler/tests/fixtures/validate/act_op_any_type.approved.txt index 9395149..eda1111 100644 --- a/src/compiler/tests/fixtures/validate/replace_first_arg.approved.txt +++ b/src/compiler/tests/fixtures/validate/act_op_any_type.approved.txt @@ -1,4 +1,4 @@ -fixture: fixtures/validate/replace_first_arg.rule +fixture: fixtures/validate/act_op_any_type.rule parse_status: 0 stderr: diff --git a/src/compiler/tests/fixtures/validate/act_op_any_type.rule b/src/compiler/tests/fixtures/validate/act_op_any_type.rule new file mode 100644 index 0000000..817de36 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/act_op_any_type.rule @@ -0,0 +1,4 @@ +v1 -> (0) op1(_, _) + +-- +#2 ->> (0) op1 diff --git a/src/compiler/tests/fixtures/validate/big_rule.approved.txt b/src/compiler/tests/fixtures/validate/big_rule.approved.txt new file mode 100644 index 0000000..00d35f6 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/big_rule.approved.txt @@ -0,0 +1,12 @@ +fixture: fixtures/validate/big_rule.rule +parse_status: 0 +stderr: + +validate_status: 0 +generated_user_conditions: + 1==size_of_vn_v_flag_0 + bb_of_op_o_extend_flag->(0)bb_of_op_o_loop + bb_of_op_o_loop->(1)bb_of_op_o_extend_flag +required_conditions: + + diff --git a/src/compiler/tests/fixtures/validate/big_rule.rule b/src/compiler/tests/fixtures/validate/big_rule.rule new file mode 100644 index 0000000..f792cdb --- /dev/null +++ b/src/compiler/tests/fixtures/validate/big_rule.rule @@ -0,0 +1,35 @@ +v_flag_0(1, _) ->(0) o_extend_flag(INT_ZEXT, bb_body) -> v_always_0; + +v_always_0 ->(0) o_mult_zero(INT_MULT, _); +#-2 ->(1) o_mult_zero -> vtmp_alw0 ->(0) o_tmp_add(INT_ADD, _); + #1 ->(1) o_tmp_add -> vtmp1 ->(1) o_ptr_add(_,_); + +v_elem_size ->(2) o_ptr_add; +v_cur1 ->(0) o_ptr_add -> v_curtmp ->(0) o_copytmp(COPY, _) -> v_cur2; + +v_orig_prt ->(0) o_cpy1(COPY, _) -> v_cur_tmp ->(0) o_get_cur -> v_cur1; + v_cur2 ->(1) o_get_cur; + +v_cur1 ->(1) o_store(STORE, _); +v_init_val ->(2) o_store; + +#0 -> (1) o_cond(INT_NOTEQUAL, _) -> vtmp2 -> (1) o_loop(CBRANCH, bb_precond); +v_elem_cnt ->(0) o_cpy(COPY, _) -> v_cnt_orig ->(0) o_cnt -> v_cnt ->(0) o_cond; + +bb_body ->(0) bb_precond; +bb_precond ->(1) bb_body + +-- +O_usercall(USERDEFINED BEFORE o_cpy); + +#76 ->>(0) O_usercall; +v_orig_prt ->>(1) O_usercall; +v_init_val ->> (2) O_usercall; +v_elem_cnt ->>(3) O_usercall; +v_elem_size ->>(4) O_usercall; + +DELETE o_store; + +#0 ->> (0) o_cpy; +#1 ->> (1) o_ptr_add + diff --git a/src/compiler/tests/fixtures/validate/conds_dom.approved.txt b/src/compiler/tests/fixtures/validate/conds_dom.approved.txt new file mode 100644 index 0000000..967663c --- /dev/null +++ b/src/compiler/tests/fixtures/validate/conds_dom.approved.txt @@ -0,0 +1,12 @@ +fixture: fixtures/validate/conds_dom.rule +parse_status: 0 +stderr: + +validate_status: 0 +generated_user_conditions: + +required_conditions: + bb_of_op_op1<=bb_of_op_op0 + bb_of_op_opA<=bb_of_op_op2 + size_of_vn_vA==size_of_vn_v0 + diff --git a/src/compiler/tests/fixtures/validate/conds_dom.rule b/src/compiler/tests/fixtures/validate/conds_dom.rule new file mode 100644 index 0000000..85b0fd3 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/conds_dom.rule @@ -0,0 +1,5 @@ +op0(INT_ADD, b0) -> v0 ->(0) op1(INT_ADD, b1) -> v1 ->(0) op2(INT_ADD, b2); +opA(INT_ADD, bA) -> vA +-- +vA ->> (0) op2; +v1 ->> (0) op0 \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/conds_trans_dom.approved.txt b/src/compiler/tests/fixtures/validate/conds_trans_dom.approved.txt new file mode 100644 index 0000000..e4fc0c0 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/conds_trans_dom.approved.txt @@ -0,0 +1,10 @@ +fixture: fixtures/validate/conds_trans_dom.rule +parse_status: 0 +stderr: + +validate_status: 0 +generated_user_conditions: + +required_conditions: + + diff --git a/src/compiler/tests/fixtures/validate/conds_trans_dom.rule b/src/compiler/tests/fixtures/validate/conds_trans_dom.rule new file mode 100644 index 0000000..a5be793 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/conds_trans_dom.rule @@ -0,0 +1,3 @@ +op0(INT_ADD, b0) -> v0 ->(0) op1(INT_ADD, b1) -> v1 ->(0) op2(INT_ADD, b2) +-- +v0 ->> (0) op2 \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/ghost_nodes_rewritte_type.approved.txt b/src/compiler/tests/fixtures/validate/ghost_nodes_rewritte_type.approved.txt new file mode 100644 index 0000000..611e730 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/ghost_nodes_rewritte_type.approved.txt @@ -0,0 +1,10 @@ +fixture: fixtures/validate/ghost_nodes_rewritte_type.rule +parse_status: 0 +stderr: + +validate_status: 0 +generated_user_conditions: + 8==size_of_vn_v1 +required_conditions: + + diff --git a/src/compiler/tests/fixtures/validate/ghost_nodes_rewritte_type.rule b/src/compiler/tests/fixtures/validate/ghost_nodes_rewritte_type.rule new file mode 100644 index 0000000..b9848c0 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/ghost_nodes_rewritte_type.rule @@ -0,0 +1,5 @@ +v1 (8, _) ->(0) op(INT_ADD, _) -> vout +-- +v2 (7) ->>(0) op ->> v4; +v3 ->>(0) op; +#1 ->>(0) op_new(COPY AFTER op) ->> vout diff --git a/src/compiler/tests/fixtures/validate/ghost_nodes_save_type.approved.txt b/src/compiler/tests/fixtures/validate/ghost_nodes_save_type.approved.txt new file mode 100644 index 0000000..ce7834b --- /dev/null +++ b/src/compiler/tests/fixtures/validate/ghost_nodes_save_type.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/ghost_nodes_save_type.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Inference Action Graph: Can't unite 7 and 8 + diff --git a/src/compiler/tests/fixtures/validate/ghost_nodes_save_type.rule b/src/compiler/tests/fixtures/validate/ghost_nodes_save_type.rule new file mode 100644 index 0000000..26a8f54 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/ghost_nodes_save_type.rule @@ -0,0 +1,3 @@ +v1 (8, _) ->(0) op(INT_ADD, _) +-- +v2 (7) ->>(0) op \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/new_pnode.approved.txt b/src/compiler/tests/fixtures/validate/new_pnode.approved.txt new file mode 100644 index 0000000..75d334a --- /dev/null +++ b/src/compiler/tests/fixtures/validate/new_pnode.approved.txt @@ -0,0 +1,10 @@ +fixture: fixtures/validate/new_pnode.rule +parse_status: 0 +stderr: + +validate_status: 0 +generated_user_conditions: + +required_conditions: + + diff --git a/src/compiler/tests/fixtures/validate/new_pnode.rule b/src/compiler/tests/fixtures/validate/new_pnode.rule new file mode 100644 index 0000000..9e7f6d4 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/new_pnode.rule @@ -0,0 +1,4 @@ +v1 ->(0) op(INT_ADD, _) +-- +v1 ->>(0) op_new(INT_ADD AFTER op); +v1 ->>(1) op_new ->> v_new diff --git a/src/compiler/tests/fixtures/validate/new_pnode_bad_struct.approved.txt b/src/compiler/tests/fixtures/validate/new_pnode_bad_struct.approved.txt new file mode 100644 index 0000000..373ae38 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/new_pnode_bad_struct.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/new_pnode_bad_struct.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Validate Action Graph: Unexpected EMPTY as 1 arg of pnode op_new expected non-Empty + diff --git a/src/compiler/tests/fixtures/validate/new_pnode_bad_struct.rule b/src/compiler/tests/fixtures/validate/new_pnode_bad_struct.rule new file mode 100644 index 0000000..4cbad8b --- /dev/null +++ b/src/compiler/tests/fixtures/validate/new_pnode_bad_struct.rule @@ -0,0 +1,3 @@ +v1 ->(0) op(INT_ADD, _) +-- +v1 ->>(0) op_new(INT_ADD AFTER op) \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/new_pnode_no_spec.approved.txt b/src/compiler/tests/fixtures/validate/new_pnode_no_spec.approved.txt new file mode 100644 index 0000000..32ec8af --- /dev/null +++ b/src/compiler/tests/fixtures/validate/new_pnode_no_spec.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/new_pnode_no_spec.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Validate Action Graph: New pnode op_new isn't specialized (OpType not set) + diff --git a/src/compiler/tests/fixtures/validate/new_pnode_no_spec.rule b/src/compiler/tests/fixtures/validate/new_pnode_no_spec.rule new file mode 100644 index 0000000..1d2c4ff --- /dev/null +++ b/src/compiler/tests/fixtures/validate/new_pnode_no_spec.rule @@ -0,0 +1,3 @@ +v1 ->(0) op(INT_ADD, _) +-- +v1 ->>(0) op_new \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/new_varnode.approved.txt b/src/compiler/tests/fixtures/validate/new_varnode.approved.txt new file mode 100644 index 0000000..0a026dd --- /dev/null +++ b/src/compiler/tests/fixtures/validate/new_varnode.approved.txt @@ -0,0 +1,10 @@ +fixture: fixtures/validate/new_varnode.rule +parse_status: 0 +stderr: + +validate_status: 0 +generated_user_conditions: + +required_conditions: + 8==size_of_vn_v1 + diff --git a/src/compiler/tests/fixtures/validate/new_varnode.rule b/src/compiler/tests/fixtures/validate/new_varnode.rule new file mode 100644 index 0000000..09ee84e --- /dev/null +++ b/src/compiler/tests/fixtures/validate/new_varnode.rule @@ -0,0 +1,3 @@ +v1 ->(0) op(INT_ADD, _) +-- +v_new(8) ->>(0) op \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/new_varnode_witohout_spec.approved.txt b/src/compiler/tests/fixtures/validate/new_varnode_witohout_spec.approved.txt new file mode 100644 index 0000000..f0a6b63 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/new_varnode_witohout_spec.approved.txt @@ -0,0 +1,10 @@ +fixture: fixtures/validate/new_varnode_witohout_spec.rule +parse_status: 0 +stderr: + +validate_status: 0 +generated_user_conditions: + +required_conditions: + 8==size_of_vn_v1 + diff --git a/src/compiler/tests/fixtures/validate/new_varnode_witohout_spec.rule b/src/compiler/tests/fixtures/validate/new_varnode_witohout_spec.rule new file mode 100644 index 0000000..09ee84e --- /dev/null +++ b/src/compiler/tests/fixtures/validate/new_varnode_witohout_spec.rule @@ -0,0 +1,3 @@ +v1 ->(0) op(INT_ADD, _) +-- +v_new(8) ->>(0) op \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/op_delete_invalid.approved.txt b/src/compiler/tests/fixtures/validate/op_delete_invalid.approved.txt new file mode 100644 index 0000000..19db6d6 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/op_delete_invalid.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/op_delete_invalid.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Validate Action Graph: Action cannot change whether varnode vout is defined by EMPTY pnode + diff --git a/src/compiler/tests/fixtures/validate/op_delete_invalid.rule b/src/compiler/tests/fixtures/validate/op_delete_invalid.rule new file mode 100644 index 0000000..0429057 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/op_delete_invalid.rule @@ -0,0 +1,3 @@ +v1 ->(0) op(INT_ADD, _) -> vout +-- +DELETE op \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/op_delete_valid.approved.txt b/src/compiler/tests/fixtures/validate/op_delete_valid.approved.txt new file mode 100644 index 0000000..bbfc182 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/op_delete_valid.approved.txt @@ -0,0 +1,10 @@ +fixture: fixtures/validate/op_delete_valid.rule +parse_status: 0 +stderr: + +validate_status: 0 +generated_user_conditions: + +required_conditions: + + diff --git a/src/compiler/tests/fixtures/validate/op_delete_valid.rule b/src/compiler/tests/fixtures/validate/op_delete_valid.rule new file mode 100644 index 0000000..aa356d5 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/op_delete_valid.rule @@ -0,0 +1,4 @@ +v1 ->(0) op(INT_ADD, _) -> vout +-- +DELETE op; +#1 ->>(0) op_new(COPY AFTER op) ->> vout \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/pat_inv_arg_of_opempty.approved.txt b/src/compiler/tests/fixtures/validate/pat_inv_arg_of_opempty.approved.txt new file mode 100644 index 0000000..b46390c --- /dev/null +++ b/src/compiler/tests/fixtures/validate/pat_inv_arg_of_opempty.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/pat_inv_arg_of_opempty.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Build Pattern Graph: EMPTY pnode cannot take v1 as an argument + diff --git a/src/compiler/tests/fixtures/validate/pat_inv_arg_of_opempty.rule b/src/compiler/tests/fixtures/validate/pat_inv_arg_of_opempty.rule new file mode 100644 index 0000000..3d65cbc --- /dev/null +++ b/src/compiler/tests/fixtures/validate/pat_inv_arg_of_opempty.rule @@ -0,0 +1,3 @@ +v1 -> (0) OPEMPTY +-- +VEMPTY \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/pat_inv_const_def.approved.txt b/src/compiler/tests/fixtures/validate/pat_inv_const_def.approved.txt new file mode 100644 index 0000000..74caec4 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/pat_inv_const_def.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/pat_inv_const_def.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Validate Pattern Graph: Const varnode 1 defined by pnode op + diff --git a/src/compiler/tests/fixtures/validate/pat_inv_const_def.rule b/src/compiler/tests/fixtures/validate/pat_inv_const_def.rule new file mode 100644 index 0000000..176aaca --- /dev/null +++ b/src/compiler/tests/fixtures/validate/pat_inv_const_def.rule @@ -0,0 +1,3 @@ +op -> #1 +-- +VEMPTY \ No newline at end of file diff --git a/src/compiler/tests/fixtures/validate/pat_inv_double_def_vnode.approved.txt b/src/compiler/tests/fixtures/validate/pat_inv_double_def_vnode.approved.txt new file mode 100644 index 0000000..c4e6386 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/pat_inv_double_def_vnode.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/pat_inv_double_def_vnode.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Build Pattern Graph: Varnode v1 already had def pnode (op) during adding op2 as new one + diff --git a/src/compiler/tests/fixtures/validate/pat_inv_double_def_vnode.rule b/src/compiler/tests/fixtures/validate/pat_inv_double_def_vnode.rule new file mode 100644 index 0000000..63d6b0e --- /dev/null +++ b/src/compiler/tests/fixtures/validate/pat_inv_double_def_vnode.rule @@ -0,0 +1,4 @@ +op(INT_ADD, _) -> v1; +op2(INT_ADD, _) -> v1 +-- +VEMPTY diff --git a/src/compiler/tests/fixtures/validate/pat_inv_op_type.approved.txt b/src/compiler/tests/fixtures/validate/pat_inv_op_type.approved.txt new file mode 100644 index 0000000..e8dcfff --- /dev/null +++ b/src/compiler/tests/fixtures/validate/pat_inv_op_type.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/pat_inv_op_type.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Validate Pattern Graph: Unexpected v1 as 2 arg of pnode op expected Empty + diff --git a/src/compiler/tests/fixtures/validate/pat_inv_op_type.rule b/src/compiler/tests/fixtures/validate/pat_inv_op_type.rule new file mode 100644 index 0000000..66fbe32 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/pat_inv_op_type.rule @@ -0,0 +1,3 @@ +v1 -> (2) op(INT_ADD, _) +-- +VEMPTY diff --git a/src/compiler/tests/fixtures/validate/pat_inv_trans_inf.approved.txt b/src/compiler/tests/fixtures/validate/pat_inv_trans_inf.approved.txt new file mode 100644 index 0000000..5d64fb9 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/pat_inv_trans_inf.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/validate/pat_inv_trans_inf.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Inference User Conditions Pattern Graph: Can't unite 6 and 2 + diff --git a/src/compiler/tests/fixtures/validate/pat_inv_trans_inf.rule b/src/compiler/tests/fixtures/validate/pat_inv_trans_inf.rule new file mode 100644 index 0000000..590089a --- /dev/null +++ b/src/compiler/tests/fixtures/validate/pat_inv_trans_inf.rule @@ -0,0 +1,12 @@ +v1(a, _) -> (0) op1(INT_ADD, _); +v2(b, _) -> (1) op1; + +vtmp2(2, _) -> (0) op2(INT_MULT, _); +v2(b, _) -> (1) op2; + +v1(a, _) -> (0) op3(INT_AND, _); +vtm1(6, _) -> (1) op3 + + +-- +VEMPTY diff --git a/src/compiler/tests/fixtures/validate/replace_first_arg.rule b/src/compiler/tests/fixtures/validate/replace_first_arg.rule deleted file mode 100644 index 36f47b0..0000000 --- a/src/compiler/tests/fixtures/validate/replace_first_arg.rule +++ /dev/null @@ -1,3 +0,0 @@ -o_tmp -> v1 -> (0) o1(INT_ADD, _) --- -#4 ->> (0) o1 diff --git a/src/compiler/tests/fixtures/validate/sanity.approved.txt b/src/compiler/tests/fixtures/validate/sanity.approved.txt new file mode 100644 index 0000000..a14d297 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/sanity.approved.txt @@ -0,0 +1,10 @@ +fixture: fixtures/validate/sanity.rule +parse_status: 0 +stderr: + +validate_status: 0 +generated_user_conditions: + +required_conditions: + + diff --git a/src/compiler/tests/fixtures/validate/sanity.rule b/src/compiler/tests/fixtures/validate/sanity.rule new file mode 100644 index 0000000..4f7dc34 --- /dev/null +++ b/src/compiler/tests/fixtures/validate/sanity.rule @@ -0,0 +1,3 @@ +VEMPTY +-- +VEMPTY diff --git a/src/compiler/tests/fixtures/validate/syntax_error.approved.txt b/src/compiler/tests/fixtures/validate/syntax_error.approved.txt index 60ae501..bb9874b 100644 --- a/src/compiler/tests/fixtures/validate/syntax_error.approved.txt +++ b/src/compiler/tests/fixtures/validate/syntax_error.approved.txt @@ -1,5 +1,5 @@ fixture: fixtures/validate/syntax_error.rule parse_status: 1 stderr: -Parser error: fixtures/validate/syntax_error.rule:3:8: syntax error, unexpected end of file, expecting pnode name +Parser error: fixtures/validate/syntax_error.rule:2:1: syntax error, unexpected varnode name, expecting -- or ; diff --git a/src/compiler/tests/fixtures/validate/syntax_error.rule b/src/compiler/tests/fixtures/validate/syntax_error.rule index 6e46faa..9dc4bcd 100644 --- a/src/compiler/tests/fixtures/validate/syntax_error.rule +++ b/src/compiler/tests/fixtures/validate/syntax_error.rule @@ -1,3 +1,2 @@ -VnIn(8, BbEntry, 16) ->(0) OpAdd(INT_ADD, BbEntry) --- -DELETE +v_orig -> (0) o_copy(COPY, _) +v_orig ->> (0) o_copy From 654f8e3284acb3ad5cdc1722ea300e8acc2ee0df Mon Sep 17 00:00:00 2001 From: Osogi Date: Sat, 30 May 2026 00:13:45 +0300 Subject: [PATCH 6/9] tests: add rulecompile test --- .../exmp_demo_obfuscated.approved.txt | 9 +++++ .../rulecompile/exmp_demo_obfuscated.rule | 16 +++++++++ .../rulecompile/exmp_mask.approved.txt | 9 +++++ .../tests/fixtures/rulecompile/exmp_mask.rule | 8 +++++ .../rulecompile/exmp_memset.approved.txt | 9 +++++ .../fixtures/rulecompile/exmp_memset.rule | 35 +++++++++++++++++++ .../rulecompile/exmp_pre_test.approved.txt | 9 +++++ .../fixtures/rulecompile/exmp_pre_test.rule | 22 ++++++++++++ .../rulecompile/exmp_set.approved.txt | 9 +++++ .../tests/fixtures/rulecompile/exmp_set.rule | 17 +++++++++ .../rulecompile/exmp_shift.approved.txt | 9 +++++ .../fixtures/rulecompile/exmp_shift.rule | 7 ++++ .../rulecompile/exmp_test.approved.txt | 9 +++++ .../tests/fixtures/rulecompile/exmp_test.rule | 17 +++++++++ .../new_varnode_autospec.approved.txt | 9 +++++ .../rulecompile/new_varnode_autospec.rule | 3 ++ .../new_varnode_autospec_inv.approved.txt | 8 +++++ .../rulecompile/new_varnode_autospec_inv.rule | 3 ++ .../no_pnode_with_type.approved.txt | 8 +++++ .../rulecompile/no_pnode_with_type.rule | 5 +++ .../no_pnode_with_type_component.approved.txt | 8 +++++ .../no_pnode_with_type_component.rule | 10 ++++++ .../replace_first_arg.approved.txt | 9 ----- .../rulecompile/replace_first_arg.rule | 3 -- .../fixtures/rulecompile/sanity.approved.txt | 9 +++++ .../tests/fixtures/rulecompile/sanity.rule | 3 ++ .../rulecompile/syntax_error.approved.txt | 2 +- .../fixtures/rulecompile/syntax_error.rule | 5 ++- .../rulecompile/validate_error.approved.txt | 7 ++++ .../fixtures/rulecompile/validate_error.rule | 6 ++++ 30 files changed, 267 insertions(+), 16 deletions(-) create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_demo_obfuscated.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_demo_obfuscated.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_mask.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_mask.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_memset.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_memset.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_pre_test.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_pre_test.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_set.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_set.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_shift.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_shift.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_test.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/exmp_test.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/new_varnode_autospec.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/new_varnode_autospec.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/new_varnode_autospec_inv.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/new_varnode_autospec_inv.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/no_pnode_with_type.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/no_pnode_with_type.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/no_pnode_with_type_component.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/no_pnode_with_type_component.rule delete mode 100644 src/compiler/tests/fixtures/rulecompile/replace_first_arg.approved.txt delete mode 100644 src/compiler/tests/fixtures/rulecompile/replace_first_arg.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/sanity.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/sanity.rule create mode 100644 src/compiler/tests/fixtures/rulecompile/validate_error.approved.txt create mode 100644 src/compiler/tests/fixtures/rulecompile/validate_error.rule diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_demo_obfuscated.approved.txt b/src/compiler/tests/fixtures/rulecompile/exmp_demo_obfuscated.approved.txt new file mode 100644 index 0000000..039a773 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_demo_obfuscated.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/rulecompile/exmp_demo_obfuscated.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 0 +pattern_steps_count: 11 +action_steps_count: 2 + diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_demo_obfuscated.rule b/src/compiler/tests/fixtures/rulecompile/exmp_demo_obfuscated.rule new file mode 100644 index 0000000..cde8309 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_demo_obfuscated.rule @@ -0,0 +1,16 @@ +o_mul (INT_MULT, _); +o_add (INT_ADD, _); +o_and (INT_AND, _); +o_xor (INT_XOR, _); + +v_param -> (0) o_and; +#1 -> (1) o_and -> v_and ->(0) o_mul; + #2 ->(1) o_mul -> v_mul ->(0) o_add; + +v_param -> (0) o_xor -> v_xor ->(1) o_add; +#1 -> (1) o_xor + +-- +v_param ->> (0) o_add; +#1 ->> (1) o_add + diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_mask.approved.txt b/src/compiler/tests/fixtures/rulecompile/exmp_mask.approved.txt new file mode 100644 index 0000000..f045f67 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_mask.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/rulecompile/exmp_mask.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 0 +pattern_steps_count: 7 +action_steps_count: 5 + diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_mask.rule b/src/compiler/tests/fixtures/rulecompile/exmp_mask.rule new file mode 100644 index 0000000..bb9d4e7 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_mask.rule @@ -0,0 +1,8 @@ +#1 -> (0) o_lft(INT_LEFT, _) -> v_res; +#121 ->(0) o_shift(USERDEFINED, _) -> v_shift_res -> (1)o_lft; +v_bit ->(1) o_shift + +-- +#117 ->>(0) o_mask(USERDEFINED BEFORE o_lft) ->> v_res; +v_bit ->>(1) o_mask; +DELETE o_lft diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_memset.approved.txt b/src/compiler/tests/fixtures/rulecompile/exmp_memset.approved.txt new file mode 100644 index 0000000..c80e956 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_memset.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/rulecompile/exmp_memset.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 0 +pattern_steps_count: 30 +action_steps_count: 9 + diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_memset.rule b/src/compiler/tests/fixtures/rulecompile/exmp_memset.rule new file mode 100644 index 0000000..f792cdb --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_memset.rule @@ -0,0 +1,35 @@ +v_flag_0(1, _) ->(0) o_extend_flag(INT_ZEXT, bb_body) -> v_always_0; + +v_always_0 ->(0) o_mult_zero(INT_MULT, _); +#-2 ->(1) o_mult_zero -> vtmp_alw0 ->(0) o_tmp_add(INT_ADD, _); + #1 ->(1) o_tmp_add -> vtmp1 ->(1) o_ptr_add(_,_); + +v_elem_size ->(2) o_ptr_add; +v_cur1 ->(0) o_ptr_add -> v_curtmp ->(0) o_copytmp(COPY, _) -> v_cur2; + +v_orig_prt ->(0) o_cpy1(COPY, _) -> v_cur_tmp ->(0) o_get_cur -> v_cur1; + v_cur2 ->(1) o_get_cur; + +v_cur1 ->(1) o_store(STORE, _); +v_init_val ->(2) o_store; + +#0 -> (1) o_cond(INT_NOTEQUAL, _) -> vtmp2 -> (1) o_loop(CBRANCH, bb_precond); +v_elem_cnt ->(0) o_cpy(COPY, _) -> v_cnt_orig ->(0) o_cnt -> v_cnt ->(0) o_cond; + +bb_body ->(0) bb_precond; +bb_precond ->(1) bb_body + +-- +O_usercall(USERDEFINED BEFORE o_cpy); + +#76 ->>(0) O_usercall; +v_orig_prt ->>(1) O_usercall; +v_init_val ->> (2) O_usercall; +v_elem_cnt ->>(3) O_usercall; +v_elem_size ->>(4) O_usercall; + +DELETE o_store; + +#0 ->> (0) o_cpy; +#1 ->> (1) o_ptr_add + diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_pre_test.approved.txt b/src/compiler/tests/fixtures/rulecompile/exmp_pre_test.approved.txt new file mode 100644 index 0000000..cd7a240 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_pre_test.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/rulecompile/exmp_pre_test.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 0 +pattern_steps_count: 18 +action_steps_count: 6 + diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_pre_test.rule b/src/compiler/tests/fixtures/rulecompile/exmp_pre_test.rule new file mode 100644 index 0000000..121b2dc --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_pre_test.rule @@ -0,0 +1,22 @@ + + v_map ->(0) o_addr; +#0x78 ->(0) o_word(USERDEFINED, _) -> v_word_res ->(1) o_addr -> vtmp ->(1) o_load(LOAD, _)-> v_mask_map; +v_bit ->(1) o_word; + + +#121 ->(0) o_shift(USERDEFINED, _) -> v_shift_res; +v_bit ->(1) o_shift; + +v_mask_map ->(0) o_right(INT_RIGHT, _) -> v_right_res; +v_shift_res ->(1) o_right; + +v_right_res ->(0) o_and(INT_AND, _) -> v_and_res ->(0) o_some; +#1 ->(1) o_and + + +-- +DELETE o_and; + +#33 ->>(0) o_pretest(USERDEFINED BEFORE o_word) ->> v_and_res; +v_map ->>(1) o_pretest; +v_bit ->>(2) o_pretest \ No newline at end of file diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_set.approved.txt b/src/compiler/tests/fixtures/rulecompile/exmp_set.approved.txt new file mode 100644 index 0000000..eb6b2ee --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_set.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/rulecompile/exmp_set.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 0 +pattern_steps_count: 15 +action_steps_count: 5 + diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_set.rule b/src/compiler/tests/fixtures/rulecompile/exmp_set.rule new file mode 100644 index 0000000..e482a26 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_set.rule @@ -0,0 +1,17 @@ +#117 ->(0) o_mask(USERDEFINED,_) -> v_mask_res; +v_bit ->(1) o_mask; + + v_map ->(0) o_addr; +#0x78 ->(0) o_word(USERDEFINED, _) -> v_word_res ->(1) o_addr -> vtmp ->(1) o_load(LOAD, _)-> v_mask_map; +v_bit ->(1) o_word; + +v_mask_res ->(0) o_or(INT_OR, _); +v_mask_map ->(1) o_or -> v_or_res ->(2) o_finstore(STORE, _) +-- +#26 ->>(0) o_set(USERDEFINED BEFORE o_mask); +v_map ->>(1) o_set; +v_bit ->>(2) o_set; + +DELETE o_finstore + + diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_shift.approved.txt b/src/compiler/tests/fixtures/rulecompile/exmp_shift.approved.txt new file mode 100644 index 0000000..6f3dff0 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_shift.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/rulecompile/exmp_shift.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 0 +pattern_steps_count: 7 +action_steps_count: 5 + diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_shift.rule b/src/compiler/tests/fixtures/rulecompile/exmp_shift.rule new file mode 100644 index 0000000..1dbbf1a --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_shift.rule @@ -0,0 +1,7 @@ +#0 -> (1) o_to_byte(SUBPIECE, _); +v_bit ->(0) o_to_byte -> v_bit_1-> (0) o_and(INT_AND, _) -> v_res; +#0x3f -> (1)o_and +-- +#121 ->>(0) o_shift(USERDEFINED BEFORE o_and) ->> v_res; +v_bit ->>(1) o_shift; +DELETE o_and \ No newline at end of file diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_test.approved.txt b/src/compiler/tests/fixtures/rulecompile/exmp_test.approved.txt new file mode 100644 index 0000000..f36c20e --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_test.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/rulecompile/exmp_test.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 0 +pattern_steps_count: 8 +action_steps_count: 6 + diff --git a/src/compiler/tests/fixtures/rulecompile/exmp_test.rule b/src/compiler/tests/fixtures/rulecompile/exmp_test.rule new file mode 100644 index 0000000..8a59340 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/exmp_test.rule @@ -0,0 +1,17 @@ +#33 ->(0) o_pretest(USERDEFINED, _) -> v_pre_test_res; +v_map ->(1) o_pretest; +v_bit ->(2) o_pretest; + +v_pre_test_res ->(0) o_cond(INT_NOTEQUAL, _) -> v_cond_res; +#0 ->(1) o_cond + + +-- +#36 ->>(0) o_test(USERDEFINED BEFORE o_pretest) ->> v_cond_res; +v_map ->>(1) o_test; +v_bit ->>(2) o_test; + + + +DELETE o_cond + diff --git a/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec.approved.txt b/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec.approved.txt new file mode 100644 index 0000000..0234519 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/rulecompile/new_varnode_autospec.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 0 +pattern_steps_count: 2 +action_steps_count: 2 + diff --git a/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec.rule b/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec.rule new file mode 100644 index 0000000..588b5c0 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec.rule @@ -0,0 +1,3 @@ +v1 ->(0) op(INT_ADD, _) +-- +v_new ->>(0) op \ No newline at end of file diff --git a/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec_inv.approved.txt b/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec_inv.approved.txt new file mode 100644 index 0000000..4eefc57 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec_inv.approved.txt @@ -0,0 +1,8 @@ +fixture: fixtures/rulecompile/new_varnode_autospec_inv.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 1 +compile_error: Can't get size value for new varnode v_new + diff --git a/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec_inv.rule b/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec_inv.rule new file mode 100644 index 0000000..d77a940 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/new_varnode_autospec_inv.rule @@ -0,0 +1,3 @@ +v1 ->(0) op(CALL, _) +-- +v_new ->>(0) op \ No newline at end of file diff --git a/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type.approved.txt b/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type.approved.txt new file mode 100644 index 0000000..1d0e090 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type.approved.txt @@ -0,0 +1,8 @@ +fixture: fixtures/rulecompile/no_pnode_with_type.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 1 +compile_error: Pattern compilation requires at least one pnode with op type + diff --git a/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type.rule b/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type.rule new file mode 100644 index 0000000..1f498fb --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type.rule @@ -0,0 +1,5 @@ +v1 -> (0) op1 -> vout; +v2 -> (1) op1 +-- +v1 ->> (1) o_userdef(USERDEFINED AFTER op1); +#1 ->> (0) o_userdef \ No newline at end of file diff --git a/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type_component.approved.txt b/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type_component.approved.txt new file mode 100644 index 0000000..aefad72 --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type_component.approved.txt @@ -0,0 +1,8 @@ +fixture: fixtures/rulecompile/no_pnode_with_type_component.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 1 +compile_error: Pattern graph contains nodes that cannot be reached from any typed pnode: op2 v3 vout2 + diff --git a/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type_component.rule b/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type_component.rule new file mode 100644 index 0000000..b5d77df --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/no_pnode_with_type_component.rule @@ -0,0 +1,10 @@ +v1 -> (0) op1(INT_ADD, _) -> vout; +v2 -> (1) op1; + +v3 -> (0) op2 -> vout2; +v3 -> (1) op2 + +-- +#1 ->> (0) o_userdef; +v1 ->> (1) o_userdef(USERDEFINED AFTER op1); +v3 ->> (2) o_userdef \ No newline at end of file diff --git a/src/compiler/tests/fixtures/rulecompile/replace_first_arg.approved.txt b/src/compiler/tests/fixtures/rulecompile/replace_first_arg.approved.txt deleted file mode 100644 index 0aec487..0000000 --- a/src/compiler/tests/fixtures/rulecompile/replace_first_arg.approved.txt +++ /dev/null @@ -1,9 +0,0 @@ -fixture: fixtures/rulecompile/replace_first_arg.rule -parse_status: 0 -stderr: - -validate_status: 0 -compile_status: 0 -pattern_steps_count: 3 -action_steps_count: 1 - diff --git a/src/compiler/tests/fixtures/rulecompile/replace_first_arg.rule b/src/compiler/tests/fixtures/rulecompile/replace_first_arg.rule deleted file mode 100644 index 36f47b0..0000000 --- a/src/compiler/tests/fixtures/rulecompile/replace_first_arg.rule +++ /dev/null @@ -1,3 +0,0 @@ -o_tmp -> v1 -> (0) o1(INT_ADD, _) --- -#4 ->> (0) o1 diff --git a/src/compiler/tests/fixtures/rulecompile/sanity.approved.txt b/src/compiler/tests/fixtures/rulecompile/sanity.approved.txt new file mode 100644 index 0000000..b8bb74c --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/sanity.approved.txt @@ -0,0 +1,9 @@ +fixture: fixtures/rulecompile/sanity.rule +parse_status: 0 +stderr: + +validate_status: 0 +compile_status: 0 +pattern_steps_count: 1 +action_steps_count: 0 + diff --git a/src/compiler/tests/fixtures/rulecompile/sanity.rule b/src/compiler/tests/fixtures/rulecompile/sanity.rule new file mode 100644 index 0000000..3884b2d --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/sanity.rule @@ -0,0 +1,3 @@ +op(INT_ADD, _) +-- +VEMPTY diff --git a/src/compiler/tests/fixtures/rulecompile/syntax_error.approved.txt b/src/compiler/tests/fixtures/rulecompile/syntax_error.approved.txt index 1421bdf..6cb6377 100644 --- a/src/compiler/tests/fixtures/rulecompile/syntax_error.approved.txt +++ b/src/compiler/tests/fixtures/rulecompile/syntax_error.approved.txt @@ -1,5 +1,5 @@ fixture: fixtures/rulecompile/syntax_error.rule parse_status: 1 stderr: -Parser error: fixtures/rulecompile/syntax_error.rule:3:8: syntax error, unexpected end of file, expecting pnode name +Parser error: fixtures/rulecompile/syntax_error.rule:2:1: syntax error, unexpected varnode name, expecting -- or ; diff --git a/src/compiler/tests/fixtures/rulecompile/syntax_error.rule b/src/compiler/tests/fixtures/rulecompile/syntax_error.rule index 6e46faa..9dc4bcd 100644 --- a/src/compiler/tests/fixtures/rulecompile/syntax_error.rule +++ b/src/compiler/tests/fixtures/rulecompile/syntax_error.rule @@ -1,3 +1,2 @@ -VnIn(8, BbEntry, 16) ->(0) OpAdd(INT_ADD, BbEntry) --- -DELETE +v_orig -> (0) o_copy(COPY, _) +v_orig ->> (0) o_copy diff --git a/src/compiler/tests/fixtures/rulecompile/validate_error.approved.txt b/src/compiler/tests/fixtures/rulecompile/validate_error.approved.txt new file mode 100644 index 0000000..6d793cc --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/validate_error.approved.txt @@ -0,0 +1,7 @@ +fixture: fixtures/rulecompile/validate_error.rule +parse_status: 0 +stderr: + +validate_status: 1 +validate_error: Validate Action Graph: Action cannot change whether varnode vtmp is defined by EMPTY pnode + diff --git a/src/compiler/tests/fixtures/rulecompile/validate_error.rule b/src/compiler/tests/fixtures/rulecompile/validate_error.rule new file mode 100644 index 0000000..af0b65a --- /dev/null +++ b/src/compiler/tests/fixtures/rulecompile/validate_error.rule @@ -0,0 +1,6 @@ +v1 -> (0) op1(INT_ADD, _) -> vtmp; + +op3(INT_AND, _) -> v2 -> (0) op2 +-- +op1 ->> v2; +op3 ->> v_new \ No newline at end of file From 1ed6986ff323c8a82496d09d12909ed46b81fcff Mon Sep 17 00:00:00 2001 From: Osogi Date: Sat, 30 May 2026 02:59:14 +0300 Subject: [PATCH 7/9] tests: add plugin tests base --- .dockerignore | 14 ++ .gitignore | 5 + Dockerfile | 23 ++- src/plugin/tests/README.md | 38 +++++ src/plugin/tests/docker/base.Dockerfile | 59 ++++++++ .../01_obfuscated/approved/main.approved.txt | 7 + .../01_obfuscated/rules/500_demo_obfuscated | 16 +++ .../01_obfuscated/target/obfuscated.elf | Bin 0 -> 15784 bytes src/plugin/tests/meson.build | 46 ++++++ src/plugin/tests/plugin_approval_test.cpp | 134 ++++++++++++++++++ .../tests/scripts/DecompileFunction.java | 38 +++++ src/plugin/tests/scripts/run-case.sh | 88 ++++++++++++ src/plugin/tests/scripts/run-docker-case.sh | 40 ++++++ .../tests/subprojects/approvaltests.wrap | 9 ++ .../packagefiles/approvaltests/meson.build | 42 ++++++ 15 files changed, 556 insertions(+), 3 deletions(-) create mode 100644 src/plugin/tests/README.md create mode 100644 src/plugin/tests/docker/base.Dockerfile create mode 100644 src/plugin/tests/fixtures/01_obfuscated/approved/main.approved.txt create mode 100644 src/plugin/tests/fixtures/01_obfuscated/rules/500_demo_obfuscated create mode 100755 src/plugin/tests/fixtures/01_obfuscated/target/obfuscated.elf create mode 100644 src/plugin/tests/meson.build create mode 100644 src/plugin/tests/plugin_approval_test.cpp create mode 100644 src/plugin/tests/scripts/DecompileFunction.java create mode 100755 src/plugin/tests/scripts/run-case.sh create mode 100755 src/plugin/tests/scripts/run-docker-case.sh create mode 100644 src/plugin/tests/subprojects/approvaltests.wrap create mode 100644 src/plugin/tests/subprojects/packagefiles/approvaltests/meson.build diff --git a/.dockerignore b/.dockerignore index 69ca821..130b1e4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,16 @@ +.git/ +venv/ +tmp/ + build/ +**/build/ +**/build-*/ +**/build*/ + +**/subprojects/.wraplock +**/subprojects/packagecache/ +**/subprojects/approvaltests/ + +**/*.received.* + Dockerfile diff --git a/.gitignore b/.gitignore index df2bb80..8364f20 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,8 @@ src/compiler/subprojects/.wraplock src/compiler/subprojects/approvaltests/ src/compiler/subprojects/packagecache/ src/compiler/tests/**/*.received.* + +src/plugin/tests/subprojects/.wraplock +src/plugin/tests/subprojects/approvaltests/ +src/plugin/tests/subprojects/packagecache/ +src/plugin/tests/fixtures/**/*.received.* diff --git a/Dockerfile b/Dockerfile index a2a3add..4c777d3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,6 @@ -FROM quay.io/pypa/manylinux2014 AS build +ARG PLUGIN_TEST_BASE_IMAGE=pcode-weaver-plugin-test-base:ghidra-12.0_reoxide-0.7.2 + +FROM quay.io/pypa/manylinux2014 AS plugin-build ARG REOXIDE_VERSION=0.7.2 ENV VIRTUAL_ENV=/venv @@ -17,12 +19,27 @@ RUN --mount=type=cache,target=/root/.cache/pip \ touch /root/.config/reoxide/reoxide.toml WORKDIR /plugin -COPY . . +COPY src/inc/ ./src/inc/ +COPY src/plugin/meson.build ./src/plugin/meson.build +COPY src/plugin/main/ ./src/plugin/main/ RUN set -ex;\ meson setup build ./src/plugin/ --buildtype release;\ meson install -C build +FROM ${PLUGIN_TEST_BASE_IMAGE} AS plugin-test + +COPY --from=plugin-build /root/.local/share/reoxide/plugins/*.so /opt/reoxide/data/plugins/ +COPY src/plugin/tests/scripts/ /opt/pcode-weaver/scripts/ +COPY scripts/install-pcodeweaver-action.sh /opt/pcode-weaver/scripts/install-pcodeweaver-action.sh + +RUN set -ex;\ + default_reoxide_yaml="$(python3 -c 'from pathlib import Path; import reoxide; print(Path(reoxide.__file__).parent / "data" / "default.yaml")')";\ + cp "${default_reoxide_yaml}" /opt/reoxide/data/current.yaml;\ + sh /opt/pcode-weaver/scripts/install-pcodeweaver-action.sh /opt/reoxide/data/current.yaml;\ + chmod +x /opt/pcode-weaver/scripts/run-case.sh \ + /opt/pcode-weaver/scripts/install-pcodeweaver-action.sh + FROM scratch -COPY --from=build /root/.local/share/reoxide/plugins/*.so . +COPY --from=plugin-build /root/.local/share/reoxide/plugins/*.so . diff --git a/src/plugin/tests/README.md b/src/plugin/tests/README.md new file mode 100644 index 0000000..82525c4 --- /dev/null +++ b/src/plugin/tests/README.md @@ -0,0 +1,38 @@ +# Plugin System Tests + +These tests run the plugin through a fixed Ghidra/ReOxide Docker environment and +compare the raw decompiled `main` output with ApprovalTests files. + +Build the reusable base image once: + +```sh +docker build \ + -f src/plugin/tests/docker/base.Dockerfile \ + -t pcode-weaver-plugin-test-base:ghidra-12.0_reoxide-0.7.2 \ + . +``` + +Build the per-checkout test image: + +```sh +docker build --target plugin-test -t pcode-weaver-plugin-test . +``` + +Run one case directly: + +```sh +cd src/compiler +meson compile -j 1 -C build +cd ../.. +src/plugin/tests/scripts/run-docker-case.sh \ + src/plugin/tests/fixtures/01_obfuscated \ + pcode-weaver-plugin-test +``` + +Run through Meson/ApprovalTests: + +```sh +cd src/plugin/tests +meson setup build +meson test -C build --print-errorlogs +``` diff --git a/src/plugin/tests/docker/base.Dockerfile b/src/plugin/tests/docker/base.Dockerfile new file mode 100644 index 0000000..f57016e --- /dev/null +++ b/src/plugin/tests/docker/base.Dockerfile @@ -0,0 +1,59 @@ +FROM eclipse-temurin:21-jdk-jammy AS ghidra-download + +ARG GHIDRA_VERSION=12.0 +ARG GHIDRA_DATE=20251205 + +ENV DEBIAN_FRONTEND=noninteractive +ENV GHIDRA_INSTALL_DIR=/opt/ghidra + +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ + set -ex;\ + apt-get update;\ + apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + unzip;\ + curl -L \ + "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_${GHIDRA_VERSION}_build/ghidra_${GHIDRA_VERSION}_PUBLIC_${GHIDRA_DATE}.zip" \ + -o /tmp/ghidra.zip;\ + unzip -q /tmp/ghidra.zip -d /opt;\ + mv "/opt/ghidra_${GHIDRA_VERSION}_PUBLIC" "${GHIDRA_INSTALL_DIR}";\ + rm /tmp/ghidra.zip + +FROM eclipse-temurin:21-jdk-jammy + +ARG REOXIDE_VERSION=0.7.2 + +ENV DEBIAN_FRONTEND=noninteractive +ENV GHIDRA_INSTALL_DIR=/opt/ghidra +ENV VIRTUAL_ENV=/opt/reoxide/reoxide-venv +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" +ENV PIP_DISABLE_PIP_VERSION_CHECK=1 + +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ + set -ex;\ + apt-get update;\ + apt-get install -y --no-install-recommends \ + ca-certificates \ + python3 \ + python3-venv;\ + python3 -m venv "${VIRTUAL_ENV}" + +RUN --mount=type=cache,target=/root/.cache/pip \ + set -ex;\ + pip install "reoxide==${REOXIDE_VERSION}" + +COPY --from=ghidra-download /opt/ghidra /opt/ghidra + +RUN set -ex;\ + mkdir -p /opt/reoxide/data/plugins;\ + printf '%s\n' \ + 'data-directory = "/opt/reoxide/data"' \ + '' \ + '[[ghidra-install]]' \ + 'enabled = true' \ + "root-dir = \"${GHIDRA_INSTALL_DIR}\"" \ + > /opt/reoxide/reoxide.toml;\ + reoxide -c /opt/reoxide/reoxide.toml link-ghidra diff --git a/src/plugin/tests/fixtures/01_obfuscated/approved/main.approved.txt b/src/plugin/tests/fixtures/01_obfuscated/approved/main.approved.txt new file mode 100644 index 0000000..dfb448f --- /dev/null +++ b/src/plugin/tests/fixtures/01_obfuscated/approved/main.approved.txt @@ -0,0 +1,7 @@ + +int main(uint param_1) + +{ + return param_1 + 1; +} + diff --git a/src/plugin/tests/fixtures/01_obfuscated/rules/500_demo_obfuscated b/src/plugin/tests/fixtures/01_obfuscated/rules/500_demo_obfuscated new file mode 100644 index 0000000..cde8309 --- /dev/null +++ b/src/plugin/tests/fixtures/01_obfuscated/rules/500_demo_obfuscated @@ -0,0 +1,16 @@ +o_mul (INT_MULT, _); +o_add (INT_ADD, _); +o_and (INT_AND, _); +o_xor (INT_XOR, _); + +v_param -> (0) o_and; +#1 -> (1) o_and -> v_and ->(0) o_mul; + #2 ->(1) o_mul -> v_mul ->(0) o_add; + +v_param -> (0) o_xor -> v_xor ->(1) o_add; +#1 -> (1) o_xor + +-- +v_param ->> (0) o_add; +#1 ->> (1) o_add + diff --git a/src/plugin/tests/fixtures/01_obfuscated/target/obfuscated.elf b/src/plugin/tests/fixtures/01_obfuscated/target/obfuscated.elf new file mode 100755 index 0000000000000000000000000000000000000000..fff7fbdf03187fce79b36db9798007e5547d81bc GIT binary patch literal 15784 zcmeHOZEPGz8J<1o!=;J8+7Oe3W(!Y`1&Kd9*6lOzGw(Yy`|RxAtZ(MaiOI2;VJM^)^$EpRyhAf_DVQCU3_)BSQQPVG zVYNqXA$yb0>GHS+D%I(FY(2IL-$KZ7-JEHHdo)cg=!70Ja@r9F;gAx54Sm>t6c(w0Ez>Z8H68R2c8pv;v~NPf?t&i9il%_BD1c{N!0h)l``i z8CC4OwoxCK-74km|L`kMJb&k1uU-D#WAAK#{Bu{o`1UV;^-K2Qesc`_aN_zfMA+s$ zx5++Qk4GsdW1H|==4W}I*x^jrPb;YR+@fO00LPB`gIDKnETdzsSIiIH5f zkePCmIj(LdUo1#eor;7(MZH!hMYU z$L!SnirnAem!-nixGo0|`}#4>^EG76kd^~{@Veg!@EBtpQw#7sevnoIJdc+sMG8a; zL<&R-L<&R-L<&R-L<+D1e`~+(pZ4OPTJ4LQe{)bN`|+w5tG{Y5zSMff7pQ*tIimks z-}fzo_PxG8SwHfvQ61m+=ZU3jpS72MZ!i9#cJEZ8uiAIjzBKd`s-V83OrCE|TkU%v z^Xnu2X=3b4o4>~Ju@!FzHGLoFsp*^Q%k6v5v*Q&(^3VGIhm#BkR_&#lefclP?8_@H zw(+ukZPmM#D%d9#wAPoW+xJqx5YOj#eu#@z<*u{#;!upU_R{O#Hv8hx7BX%esMqT^ z(sX!v^S|h=+jx*-*Tw(w92Ig!XDM#!;dkw&O6_9e-Nl-*^djT3VN{J*AH34gvY{TI zNt7Z5A_XD^A_XD^A_XD^A_XD^A_XD^A_XD^{{IT_?_b95mXGhJuJG?idusLiX9({m zy?%KiPisxz_XQ*sh~@9=gN-xscWr zi#;jp96uyB)i7BOON;w-;>QqpT$mAWqFAJDYA zAb7K2x8M#zfP|^4tbg1p1-;S``cW007JK>$_1z{m{NAbS{*q2UwJNs12$y{6mtp^W zpd-De`gTpu=O1FDUsC=54zND_zpN4KQpZO|j+*<=CMyN6V)pe}16FTOU&S~39_jD5 zdIzjS2c+OXHOYExQg7D7KCHJvB~OSTra0U}*vy}=M@+S;IT?@Qu1w*d4e^JB$M}Z- z1Z51>tvceG!S&)*)&~9e0^?PeD)lAGaJ#r)!1FjX)GZ3*AN+SH)2#m+o!1L~Jzc75 zqJ}kWR?myRKaKX#^?t<<>r|V}wRq0`mOh61VB06X(w*I@51To6ofNNoFOz4w=*;Ab zNjK-Dy<(~CxRrU8D(2^M884HzdYgOj8vLx|mP+n|lPP$m1vOoA^BE^y$>$d+Bw#t@ z>8*1uCZ{Xql*`qp$an1Y@QH+zI63Ojn)}fQP7a@#7$KTAFE|NXO6}3p${C+Lb$ocz zIW;zRCNbqq4IiIOP(*kSKpZRo-)pshChdBz^3Q~7VM8zdCu99S04H58I;M8^(31XYWVm>4-X07ebz0{Dl5HE zpe8hWC0+7`OsSkL7S<`U>X z=1)MhkNH!$|1QPz+zIiRUjd(#cDawNGvYBX$`Z$4*@(w{4anb%!Nhe0)91jM?3FVFFw>-x& z50+~DwvcE1CVhhOro;ioY=poDJ{OAbl>#9APyuYn_*B`{M zDbq$DnYK3Of7n+T_J<98jbhsa@tAL}^bko2e%e~I!M{NTJoeCjV;(5`M5}WBc>Hrh z9IoTHiDMVUorSQ2IF<(x%^6 V$@OAJ$&s`!7_T`Zq%$tgHY4 literal 0 HcmV?d00001 diff --git a/src/plugin/tests/meson.build b/src/plugin/tests/meson.build new file mode 100644 index 0000000..9bfd2d9 --- /dev/null +++ b/src/plugin/tests/meson.build @@ -0,0 +1,46 @@ +project( + 'pcode-weaver-plugin-system-tests', + 'cpp', + meson_version: '>=1.10.0', + default_options: [ + 'cpp_std=c++17', + ], +) + +approvaltests_dep = dependency( + 'approvaltests', + fallback: ['approvaltests', 'approvaltests_dep'], +) + +plugin_approval_test = executable( + 'plugin_approval_test', + 'plugin_approval_test.cpp', + cpp_args: ['-DAPPROVAL_TESTS_DISABLE_FILE_MACRO_CHECK'], + dependencies: [ + approvaltests_dep, + ], +) + +cases_find = run_command( + 'find', + 'fixtures', + '-mindepth', + '1', + '-maxdepth', + '1', + '-type', + 'd', + check: true, +) + +cases = cases_find.stdout().strip().split('\n') + +foreach case_dir : cases + test( + 'plugin / ' + case_dir.split('/')[-1], + plugin_approval_test, + args: [case_dir], + workdir: meson.current_source_dir(), + timeout: 600, + ) +endforeach diff --git a/src/plugin/tests/plugin_approval_test.cpp b/src/plugin/tests/plugin_approval_test.cpp new file mode 100644 index 0000000..83e7a29 --- /dev/null +++ b/src/plugin/tests/plugin_approval_test.cpp @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: © 2026 Efremov Alexey <4osogi@gmail.com> + +#include "ApprovalTests/ApprovalTests.hpp" +#include "ApprovalTests/core/ApprovalNamer.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +namespace fs = std::filesystem; + +class CaseNamer : public ApprovalTests::ApprovalNamer { +public: + explicit CaseNamer(fs::path caseDir) : caseDir(std::move(caseDir)) {} + + std::string getApprovedFile(std::string) const override { + return (caseDir / "approved" / "main.approved.txt").string(); + } + + std::string getReceivedFile(std::string) const override { + return (caseDir / "approved" / "main.received.txt").string(); + } + +private: + fs::path caseDir; +}; + +std::string shellQuote(const fs::path &path) { + std::string input = path.string(); + std::string quoted = "'"; + for (const char ch : input) { + if (ch == '\'') { + quoted += "'\\''"; + } else { + quoted += ch; + } + } + quoted += "'"; + return quoted; +} + +std::string shellQuote(const std::string &input) { + std::string quoted = "'"; + for (const char ch : input) { + if (ch == '\'') { + quoted += "'\\''"; + } else { + quoted += ch; + } + } + quoted += "'"; + return quoted; +} + +std::string getenvOr(std::string_view name, std::string fallback) { + const char *value = std::getenv(std::string(name).c_str()); + if (value == nullptr || *value == '\0') { + return fallback; + } + return value; +} + +std::string runCase(const fs::path &caseDir) { + const fs::path script = fs::current_path() / "scripts" / "run-docker-case.sh"; + const std::string image = getenvOr( + "PCODE_WEAVER_PLUGIN_TEST_IMAGE", "pcode-weaver-plugin-test:latest" + ); + const std::string command = shellQuote(script) + " " + + shellQuote(fs::absolute(caseDir)) + " " + + shellQuote(image); + + std::array buffer{}; + std::string output; + + FILE *pipe = popen(command.c_str(), "r"); + if (pipe == nullptr) { + throw std::runtime_error("failed to start plugin test runner"); + } + + while (fgets(buffer.data(), static_cast(buffer.size()), pipe) != + nullptr) { + output += buffer.data(); + } + + const int status = pclose(pipe); + if (status == -1) { + throw std::runtime_error("failed to close plugin test runner"); + } + + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + throw std::runtime_error( + "plugin test runner failed for " + caseDir.string() + ); + } + + return output; +} + +} // namespace + +int main(int argc, char **argv) { + if (argc != 2) { + std::cerr << "usage: " << argv[0] << " \n"; + return EXIT_FAILURE; + } + + const fs::path caseDir = argv[1]; + + try { + static const ApprovalTests::QuietReporter quietReporter; + ApprovalTests::Approvals::verify( + runCase(caseDir), + ApprovalTests::Options() + .withReporter(quietReporter) + .withNamer(std::make_shared(caseDir)) + ); + } catch (const std::exception &ex) { + std::cerr << ex.what() << "\n"; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src/plugin/tests/scripts/DecompileFunction.java b/src/plugin/tests/scripts/DecompileFunction.java new file mode 100644 index 0000000..de5f3e7 --- /dev/null +++ b/src/plugin/tests/scripts/DecompileFunction.java @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: © 2026 Efremov Alexey <4osogi@gmail.com> + +import ghidra.app.decompiler.DecompInterface; +import ghidra.app.decompiler.DecompileResults; +import ghidra.app.script.GhidraScript; +import ghidra.program.model.listing.Function; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +public class DecompileFunction extends GhidraScript { + @Override + public void run() throws Exception { + String[] args = getScriptArgs(); + String functionName = args.length > 0 ? args[0] : "main"; + Path outputPath = Path.of(args.length > 1 ? args[1] : "decompiled.c"); + + List functions = getGlobalFunctions(functionName); + if (functions.isEmpty()) { + throw new IllegalStateException("function not found: " + functionName); + } + + DecompInterface decompiler = new DecompInterface(); + decompiler.openProgram(currentProgram); + DecompileResults results = + decompiler.decompileFunction(functions.get(0), 120, monitor); + if (!results.decompileCompleted()) { + throw new IllegalStateException( + "decompile failed: " + results.getErrorMessage() + ); + } + + Files.writeString(outputPath, results.getDecompiledFunction().getC()); + decompiler.dispose(); + } +} diff --git a/src/plugin/tests/scripts/run-case.sh b/src/plugin/tests/scripts/run-case.sh new file mode 100755 index 0000000..0f5b657 --- /dev/null +++ b/src/plugin/tests/scripts/run-case.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ $# -ne 2 ]]; then + echo "usage: $0 " >&2 + exit 2 +fi + +case_dir=$1 +rules_dir=$2 +work_dir=$(mktemp -d) +project_dir="${work_dir}/ghidra-project" +output_file="${work_dir}/main.c" +reoxide_log="${work_dir}/reoxided.log" +ghidra_log="${work_dir}/ghidra.log" +ghidra_timeout_seconds="${GHIDRA_TIMEOUT_SECONDS:-240}" + +cleanup() { + if [[ -n "${reoxide_pid:-}" ]]; then + kill "${reoxide_pid}" >/dev/null 2>&1 || true + wait "${reoxide_pid}" >/dev/null 2>&1 || true + fi + rm -rf "${work_dir}" +} +trap cleanup EXIT + +mkdir -p "${project_dir}" + +mapfile -t binaries < <(find "${case_dir}/target" -maxdepth 1 -type f -name '*.elf' | sort) +if [[ ${#binaries[@]} -ne 1 ]]; then + echo "expected exactly one ELF in ${case_dir}/target, found ${#binaries[@]}" >&2 + exit 1 +fi + +export PCODE_WEAVER_RULE_DIR="${rules_dir}" +export REOXIDE_CONFIG=/opt/reoxide/reoxide.toml +export REOXIDE_BIND="ipc://${work_dir}/reoxide.sock" +export REOXIDE_HOST="${REOXIDE_BIND}" +export REOXIDE_MANAGE_BIND="ipc://${work_dir}/reoxide-manage.sock" +export REOXIDE_MANAGE_HOST="${REOXIDE_MANAGE_BIND}" + +echo "plugin-test: starting reoxided" >&2 +reoxided -c "${REOXIDE_CONFIG}" -b "${REOXIDE_BIND}" -m "${REOXIDE_MANAGE_BIND}" \ + >"${reoxide_log}" 2>&1 & +reoxide_pid=$! + +reoxide_ready=false +for _ in $(seq 1 50); do + if [[ -e "${work_dir}/reoxide-manage.sock" ]]; then + reoxide_ready=true + break + fi + if ! kill -0 "${reoxide_pid}" >/dev/null 2>&1; then + break + fi + sleep 0.1 +done + +if [[ "${reoxide_ready}" != true ]]; then + echo "reoxided did not become ready" >&2 + cat "${reoxide_log}" >&2 + exit 1 +fi + +if ! kill -0 "${reoxide_pid}" >/dev/null 2>&1; then + echo "reoxided exited before Ghidra started" >&2 + cat "${reoxide_log}" >&2 + exit 1 +fi + +echo "plugin-test: running Ghidra headless decompile for ${binaries[0]}" >&2 +if ! timeout "${ghidra_timeout_seconds}s" "${GHIDRA_INSTALL_DIR}/support/analyzeHeadless" \ + "${project_dir}" pcode-weaver-plugin-test \ + -import "${binaries[0]}" \ + -scriptPath /opt/pcode-weaver/scripts \ + -postScript DecompileFunction.java main "${output_file}" \ + -deleteProject \ + >"${ghidra_log}" 2>&1; then + echo "Ghidra headless run failed or timed out after ${ghidra_timeout_seconds}s" >&2 + echo "----- ghidra.log -----" >&2 + cat "${ghidra_log}" >&2 + echo "----- reoxided.log -----" >&2 + cat "${reoxide_log}" >&2 + exit 1 +fi + +echo "plugin-test: decompile finished" >&2 +cat "${output_file}" diff --git a/src/plugin/tests/scripts/run-docker-case.sh b/src/plugin/tests/scripts/run-docker-case.sh new file mode 100755 index 0000000..10359fc --- /dev/null +++ b/src/plugin/tests/scripts/run-docker-case.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ $# -lt 1 || $# -gt 2 ]]; then + echo "usage: $0 [docker-image]" >&2 + exit 2 +fi + +case_dir=$(realpath "$1") +image="${2:-${PCODE_WEAVER_PLUGIN_TEST_IMAGE:-pcode-weaver-plugin-test:latest}}" +repo_root=$(git -C "$(dirname "$0")" rev-parse --show-toplevel) +compiler="${repo_root}/src/compiler/build/bin/compiler.elf" +work_dir=$(mktemp -d) +rules_dir="${work_dir}/compiled-rules" + +cleanup() { + rm -rf "${work_dir}" +} +trap cleanup EXIT + +if [[ ! -x "${compiler}" ]]; then + echo "compiler not found or not executable: ${compiler}" >&2 + echo "build it first from src/compiler with: meson compile -j 1 -C build" >&2 + exit 1 +fi + +mapfile -t rules < <(find "${case_dir}/rules" -maxdepth 1 -type f | sort) +if [[ ${#rules[@]} -eq 0 ]]; then + echo "no rules found in ${case_dir}/rules" >&2 + exit 1 +fi + +mkdir -p "${rules_dir}" +"${compiler}" -d "${rules_dir}" "${rules[@]}" >&2 + +docker run --rm \ + --volume "${case_dir}:/case:ro" \ + --volume "${rules_dir}:/compiled-rules:ro" \ + "${image}" \ + /opt/pcode-weaver/scripts/run-case.sh /case /compiled-rules diff --git a/src/plugin/tests/subprojects/approvaltests.wrap b/src/plugin/tests/subprojects/approvaltests.wrap new file mode 100644 index 0000000..13e345a --- /dev/null +++ b/src/plugin/tests/subprojects/approvaltests.wrap @@ -0,0 +1,9 @@ +[wrap-git] +url = https://github.com/approvals/ApprovalTests.cpp.git +revision = v.10.13.0 +depth = 1 +method = meson +patch_directory = approvaltests + +[provide] +approvaltests = approvaltests_dep diff --git a/src/plugin/tests/subprojects/packagefiles/approvaltests/meson.build b/src/plugin/tests/subprojects/packagefiles/approvaltests/meson.build new file mode 100644 index 0000000..fdd1af8 --- /dev/null +++ b/src/plugin/tests/subprojects/packagefiles/approvaltests/meson.build @@ -0,0 +1,42 @@ +project( + 'approvaltests', + 'cpp', + version: '10.13.0', +) + +approvaltests_sources_text = run_command( + 'find', + 'ApprovalTests', + '-name', + '*.cpp', + check: true, +).stdout().strip() + +approvaltests_sources = [] +if approvaltests_sources_text != '' + approvaltests_sources = approvaltests_sources_text.split('\n') +endif + +approvaltests_inc = [ + include_directories('.'), + include_directories('ApprovalTests'), +] + +approvaltests_dep = declare_dependency( + include_directories: approvaltests_inc, +) + +if approvaltests_sources.length() != 0 + approvaltests_lib = static_library( + 'approvaltests', + approvaltests_sources, + include_directories: approvaltests_inc, + ) + + approvaltests_dep = declare_dependency( + include_directories: approvaltests_inc, + link_with: approvaltests_lib, + ) +endif + +meson.override_dependency('approvaltests', approvaltests_dep) From 421d1abee3a3ef734efa3002260aec5885f33f16 Mon Sep 17 00:00:00 2001 From: Osogi Date: Sat, 30 May 2026 03:09:38 +0300 Subject: [PATCH 8/9] tests: add plugin tests --- .../01_obfuscated/approved/main.approved.txt | 1 + .../02_obfuscated2/approved/main.approved.txt | 160 ++++++++++++++++++ .../fixtures/02_obfuscated2/rules/010_predemo | 6 + .../fixtures/02_obfuscated2/rules/011_predemo | 6 + .../02_obfuscated2/rules/100_demo_and_reorder | 5 + .../02_obfuscated2/rules/110_demo_xor_reorder | 5 + .../02_obfuscated2/rules/120_demo_mul_reorder | 5 + .../02_obfuscated2/rules/200_demo_add_reorder | 5 + .../02_obfuscated2/rules/500_demo_obfuscated | 16 ++ .../02_obfuscated2/target/obfuscated2.elf | Bin 0 -> 15808 bytes .../03_memset/approved/main.approved.txt | 153 +++++++++++++++++ .../tests/fixtures/03_memset/rules/300_memset | 35 ++++ .../fixtures/03_memset/target/memset.elf | Bin 0 -> 16064 bytes .../04_bitmap/approved/main.approved.txt | 89 ++++++++++ .../tests/fixtures/04_bitmap/rules/100_word | 6 + .../tests/fixtures/04_bitmap/rules/200_shift | 7 + .../tests/fixtures/04_bitmap/rules/300_mask | 8 + .../04_bitmap/rules/330_mask_reorder_or | 8 + .../tests/fixtures/04_bitmap/rules/400_set | 17 ++ .../fixtures/04_bitmap/rules/410_set_alt | 17 ++ .../tests/fixtures/04_bitmap/rules/500_clear | 18 ++ .../fixtures/04_bitmap/rules/600_pre_test | 22 +++ .../fixtures/04_bitmap/rules/600_pre_test_alt | 22 +++ .../tests/fixtures/04_bitmap/rules/610_test | 17 ++ .../fixtures/04_bitmap/rules/610_test_alt | 16 ++ .../fixtures/04_bitmap/target/bitmap.elf | Bin 0 -> 16056 bytes 26 files changed, 644 insertions(+) create mode 100644 src/plugin/tests/fixtures/02_obfuscated2/approved/main.approved.txt create mode 100644 src/plugin/tests/fixtures/02_obfuscated2/rules/010_predemo create mode 100644 src/plugin/tests/fixtures/02_obfuscated2/rules/011_predemo create mode 100644 src/plugin/tests/fixtures/02_obfuscated2/rules/100_demo_and_reorder create mode 100644 src/plugin/tests/fixtures/02_obfuscated2/rules/110_demo_xor_reorder create mode 100644 src/plugin/tests/fixtures/02_obfuscated2/rules/120_demo_mul_reorder create mode 100644 src/plugin/tests/fixtures/02_obfuscated2/rules/200_demo_add_reorder create mode 100644 src/plugin/tests/fixtures/02_obfuscated2/rules/500_demo_obfuscated create mode 100755 src/plugin/tests/fixtures/02_obfuscated2/target/obfuscated2.elf create mode 100644 src/plugin/tests/fixtures/03_memset/approved/main.approved.txt create mode 100644 src/plugin/tests/fixtures/03_memset/rules/300_memset create mode 100755 src/plugin/tests/fixtures/03_memset/target/memset.elf create mode 100644 src/plugin/tests/fixtures/04_bitmap/approved/main.approved.txt create mode 100644 src/plugin/tests/fixtures/04_bitmap/rules/100_word create mode 100644 src/plugin/tests/fixtures/04_bitmap/rules/200_shift create mode 100644 src/plugin/tests/fixtures/04_bitmap/rules/300_mask create mode 100644 src/plugin/tests/fixtures/04_bitmap/rules/330_mask_reorder_or create mode 100644 src/plugin/tests/fixtures/04_bitmap/rules/400_set create mode 100644 src/plugin/tests/fixtures/04_bitmap/rules/410_set_alt create mode 100644 src/plugin/tests/fixtures/04_bitmap/rules/500_clear create mode 100644 src/plugin/tests/fixtures/04_bitmap/rules/600_pre_test create mode 100644 src/plugin/tests/fixtures/04_bitmap/rules/600_pre_test_alt create mode 100644 src/plugin/tests/fixtures/04_bitmap/rules/610_test create mode 100644 src/plugin/tests/fixtures/04_bitmap/rules/610_test_alt create mode 100755 src/plugin/tests/fixtures/04_bitmap/target/bitmap.elf diff --git a/src/plugin/tests/fixtures/01_obfuscated/approved/main.approved.txt b/src/plugin/tests/fixtures/01_obfuscated/approved/main.approved.txt index dfb448f..f9bb8d2 100644 --- a/src/plugin/tests/fixtures/01_obfuscated/approved/main.approved.txt +++ b/src/plugin/tests/fixtures/01_obfuscated/approved/main.approved.txt @@ -5,3 +5,4 @@ int main(uint param_1) return param_1 + 1; } + diff --git a/src/plugin/tests/fixtures/02_obfuscated2/approved/main.approved.txt b/src/plugin/tests/fixtures/02_obfuscated2/approved/main.approved.txt new file mode 100644 index 0000000..767924b --- /dev/null +++ b/src/plugin/tests/fixtures/02_obfuscated2/approved/main.approved.txt @@ -0,0 +1,160 @@ + +int main(undefined4 param_1) + +{ + int iVar1; + uint uVar2; + uint uVar3; + uint uVar4; + uint uVar5; + undefined4 local_24; + + local_24 = 0; + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(param_1); + uVar3 = id(1); + iVar1 = id(2); + uVar4 = id(param_1); + uVar5 = id(1); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(param_1); + uVar3 = id(1); + iVar1 = id(2); + uVar4 = id(1); + uVar5 = id(param_1); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(1); + uVar3 = id(param_1); + iVar1 = id(2); + uVar4 = id(param_1); + uVar5 = id(1); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(1); + uVar3 = id(param_1); + iVar1 = id(2); + uVar4 = id(1); + uVar5 = id(param_1); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + iVar1 = id(2); + uVar2 = id(param_1); + uVar3 = id(1); + uVar4 = id(param_1); + uVar5 = id(1); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + iVar1 = id(2); + uVar2 = id(param_1); + uVar3 = id(1); + uVar4 = id(1); + uVar5 = id(param_1); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + iVar1 = id(2); + uVar2 = id(1); + uVar3 = id(param_1); + uVar4 = id(param_1); + uVar5 = id(1); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + iVar1 = id(2); + uVar2 = id(1); + uVar3 = id(param_1); + uVar4 = id(1); + uVar5 = id(param_1); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(param_1); + uVar3 = id(1); + uVar4 = id(param_1); + uVar5 = id(1); + iVar1 = id(2); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(1); + uVar3 = id(param_1); + uVar4 = id(param_1); + uVar5 = id(1); + iVar1 = id(2); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(param_1); + uVar3 = id(1); + uVar4 = id(1); + uVar5 = id(param_1); + iVar1 = id(2); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(1); + uVar3 = id(param_1); + uVar4 = id(1); + uVar5 = id(param_1); + iVar1 = id(2); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(param_1); + uVar3 = id(1); + iVar1 = id(2); + uVar4 = id(param_1); + uVar5 = id(1); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(1); + uVar3 = id(param_1); + iVar1 = id(2); + uVar4 = id(param_1); + uVar5 = id(1); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(param_1); + uVar3 = id(1); + iVar1 = id(2); + uVar4 = id(1); + uVar5 = id(param_1); + local_24 = param_1 + 1; + } + iVar1 = id(1); + if (1 != 0) { + uVar2 = id(1); + uVar3 = id(param_1); + iVar1 = id(2); + uVar4 = id(1); + uVar5 = id(param_1); + local_24 = param_1 + 1; + } + return local_24; +} + + diff --git a/src/plugin/tests/fixtures/02_obfuscated2/rules/010_predemo b/src/plugin/tests/fixtures/02_obfuscated2/rules/010_predemo new file mode 100644 index 0000000..52e3d68 --- /dev/null +++ b/src/plugin/tests/fixtures/02_obfuscated2/rules/010_predemo @@ -0,0 +1,6 @@ +v_id_addr (_, _, 0x0101129) ->(0) o_call_id(CALL, _); +v_id_arg ->(1) o_call_id -> vres ->(0) o_op(_, _) + +-- + +v_id_arg ->> (0) o_op \ No newline at end of file diff --git a/src/plugin/tests/fixtures/02_obfuscated2/rules/011_predemo b/src/plugin/tests/fixtures/02_obfuscated2/rules/011_predemo new file mode 100644 index 0000000..f51a5d5 --- /dev/null +++ b/src/plugin/tests/fixtures/02_obfuscated2/rules/011_predemo @@ -0,0 +1,6 @@ +v_id_addr (_, _, 0x0101129) ->(0) o_call_id(CALL, _); +v_id_arg ->(1) o_call_id -> vres ->(1) o_op(_, _) + +-- + +v_id_arg ->> (1) o_op \ No newline at end of file diff --git a/src/plugin/tests/fixtures/02_obfuscated2/rules/100_demo_and_reorder b/src/plugin/tests/fixtures/02_obfuscated2/rules/100_demo_and_reorder new file mode 100644 index 0000000..e34ca60 --- /dev/null +++ b/src/plugin/tests/fixtures/02_obfuscated2/rules/100_demo_and_reorder @@ -0,0 +1,5 @@ +#1 -> (0) o_and(INT_AND, _); +v1 -> (1) o_and +-- +v1 ->> (0) o_and; +#1 ->> (1) o_and \ No newline at end of file diff --git a/src/plugin/tests/fixtures/02_obfuscated2/rules/110_demo_xor_reorder b/src/plugin/tests/fixtures/02_obfuscated2/rules/110_demo_xor_reorder new file mode 100644 index 0000000..37f083f --- /dev/null +++ b/src/plugin/tests/fixtures/02_obfuscated2/rules/110_demo_xor_reorder @@ -0,0 +1,5 @@ +#1 -> (0) o_xor(INT_XOR, _); +v1 -> (1) o_xor +-- +v1 ->> (0) o_xor; +#1 ->> (1) o_xor \ No newline at end of file diff --git a/src/plugin/tests/fixtures/02_obfuscated2/rules/120_demo_mul_reorder b/src/plugin/tests/fixtures/02_obfuscated2/rules/120_demo_mul_reorder new file mode 100644 index 0000000..dc9c994 --- /dev/null +++ b/src/plugin/tests/fixtures/02_obfuscated2/rules/120_demo_mul_reorder @@ -0,0 +1,5 @@ +#2 -> (0) o_mul(INT_MULT, _); +v1 -> (1) o_mul +-- +v1 ->> (0) o_mul; +#2 ->> (1) o_mul \ No newline at end of file diff --git a/src/plugin/tests/fixtures/02_obfuscated2/rules/200_demo_add_reorder b/src/plugin/tests/fixtures/02_obfuscated2/rules/200_demo_add_reorder new file mode 100644 index 0000000..8ee9cb9 --- /dev/null +++ b/src/plugin/tests/fixtures/02_obfuscated2/rules/200_demo_add_reorder @@ -0,0 +1,5 @@ +o_mul(INT_MULT, _) -> v_mul_res ->(1) o_add (INT_ADD, _); + v1 ->(0) o_add +-- +v1 ->> (1) o_add; +v_mul_res ->> (0) o_add \ No newline at end of file diff --git a/src/plugin/tests/fixtures/02_obfuscated2/rules/500_demo_obfuscated b/src/plugin/tests/fixtures/02_obfuscated2/rules/500_demo_obfuscated new file mode 100644 index 0000000..cde8309 --- /dev/null +++ b/src/plugin/tests/fixtures/02_obfuscated2/rules/500_demo_obfuscated @@ -0,0 +1,16 @@ +o_mul (INT_MULT, _); +o_add (INT_ADD, _); +o_and (INT_AND, _); +o_xor (INT_XOR, _); + +v_param -> (0) o_and; +#1 -> (1) o_and -> v_and ->(0) o_mul; + #2 ->(1) o_mul -> v_mul ->(0) o_add; + +v_param -> (0) o_xor -> v_xor ->(1) o_add; +#1 -> (1) o_xor + +-- +v_param ->> (0) o_add; +#1 ->> (1) o_add + diff --git a/src/plugin/tests/fixtures/02_obfuscated2/target/obfuscated2.elf b/src/plugin/tests/fixtures/02_obfuscated2/target/obfuscated2.elf new file mode 100755 index 0000000000000000000000000000000000000000..ed3efa0ceb9a44c2003013283446c99f154fa867 GIT binary patch literal 15808 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 kGdy;vc6*Axh@kzBJ5r_`t5&6;{OO08&NNA^-pY literal 0 HcmV?d00001 diff --git a/src/plugin/tests/fixtures/03_memset/approved/main.approved.txt b/src/plugin/tests/fixtures/03_memset/approved/main.approved.txt new file mode 100644 index 0000000..0fb3f51 --- /dev/null +++ b/src/plugin/tests/fixtures/03_memset/approved/main.approved.txt @@ -0,0 +1,153 @@ + +uint main(int param_1,long param_2) + +{ + undefined1 auVar1 [16]; + ulong uVar2; + long lVar3; + ulong uVar4; + ulong uVar5; + ulong *puVar6; + undefined8 *puVar7; + ulong *puVar8; + long *plVar9; + ulonglong uVar10; + uint uVar11; + long in_FS_OFFSET; + byte bVar12; + ulong local_148 [3]; + ulong local_130 [2]; + ulong local_120; + long local_118 [4]; + undefined8 local_f8 [4]; + ulong local_d8 [6]; + undefined8 local_a8 [4]; + ulong local_88; + ulong local_80; + ulong local_78; + ulong local_70; + ulong local_68 [9]; + long local_20; + + bVar12 = 0; + uVar10 = 0x2a; + local_20 = *(long *)(in_FS_OFFSET + 0x28); + if (1 < param_1) { + uVar10 = strtoull(*(char **)(param_2 + 8),(char **)0x0,0); + } + uVar11 = (uint)uVar10 & 3; + puVar6 = &local_88; + skinit(&local_88,0,0xc,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + puVar6 = puVar6 + 1; + } + local_88 = uVar10; + local_70 = 0x1000; + auVar1._8_8_ = 0; + auVar1._0_8_ = uVar10; + local_80 = (uVar10 - ((SUB168(auVar1 * ZEXT816(0xf0f0f0f0f0f0f0f1),8) & 0xfffffffffffffff0) + + uVar10 / 0x11)) + 1000; + if ((uVar10 & 1) == 0) { + plVar9 = local_118; + skinit(local_118,-1,8,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + plVar9 = plVar9 + 1; + } + local_78 = local_78 | 1; + } + else { + plVar9 = local_118; + skinit(local_118,(ulong)((uint)uVar10 & 0xf) * 0x1111111111111111,4,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + plVar9 = plVar9 + 1; + } + puVar7 = local_f8; + skinit(local_f8,0xeeeeeeeeeeeeeeee,4,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + puVar7 = puVar7 + 1; + } + local_78 = local_78 | 2; + } + uVar5 = 0; + uVar4 = 0; + puVar6 = local_d8; + do { + uVar2 = uVar10 >> ((byte)uVar4 & 0x3f); + if ((uVar2 & 1) == 0) { + puVar8 = puVar6; + skinit(puVar6,(ulong)((uint)uVar2 & 1),3,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + puVar8 = puVar8 + 1; + } + } + else { + puVar8 = puVar6; + skinit(puVar6,uVar10 + uVar4 ^ 0xcccccccccccccccc,3,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + puVar8 = puVar8 + 1; + } + } + uVar2 = uVar4 + 1; + uVar5 = uVar5 ^ local_118[uVar4] + puVar6[1]; + *puVar6 = uVar4 | 0x5041434b00000000; + uVar4 = uVar2; + puVar6 = puVar6 + 3; + } while (uVar2 != 3); + if (uVar11 == 1) { + puVar6 = local_148; + skinit(local_148,0xabababababababab,6,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + puVar6 = puVar6 + 1; + } + local_120 = local_80; + } + else if (uVar11 == 2) { + puVar6 = local_148; + skinit(local_148,uVar5,3,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + puVar6 = puVar6 + 1; + } + puVar6 = local_130; + skinit(local_130,~uVar5,3,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + puVar6 = puVar6 + 1; + } + } + else if ((uVar10 & 3) == 0) { + puVar6 = local_148; + skinit(local_148,0,6,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + puVar6 = puVar6 + 1; + } + local_148[0] = local_88; + } + else { + puVar6 = local_148; + skinit(local_148,uVar10 | 0xdead000000000000,6,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + puVar6 = puVar6 + 1; + } + if (0x400 < local_70) { + puVar6 = local_68; + skinit(local_68,uVar10,8,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + puVar6 = puVar6 + 1; + } + } + } + if ((local_148[0] ^ local_120) == uVar10) { + puVar7 = local_a8; + skinit(local_a8,0x7777777777777777,4,8); + for (lVar3 = 0; lVar3 != 0; lVar3 = lVar3 + -1) { + puVar7 = puVar7 + 1; + } + } + __printf_chk(1,"%llu %llu %llx %llx %llx\n",local_80,local_78,local_118[0],local_a8[0],local_120); + if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) { + /* WARNING: Subroutine does not return */ + __stack_chk_fail(); + } + return (uint)uVar5 & 7; +} + + diff --git a/src/plugin/tests/fixtures/03_memset/rules/300_memset b/src/plugin/tests/fixtures/03_memset/rules/300_memset new file mode 100644 index 0000000..f792cdb --- /dev/null +++ b/src/plugin/tests/fixtures/03_memset/rules/300_memset @@ -0,0 +1,35 @@ +v_flag_0(1, _) ->(0) o_extend_flag(INT_ZEXT, bb_body) -> v_always_0; + +v_always_0 ->(0) o_mult_zero(INT_MULT, _); +#-2 ->(1) o_mult_zero -> vtmp_alw0 ->(0) o_tmp_add(INT_ADD, _); + #1 ->(1) o_tmp_add -> vtmp1 ->(1) o_ptr_add(_,_); + +v_elem_size ->(2) o_ptr_add; +v_cur1 ->(0) o_ptr_add -> v_curtmp ->(0) o_copytmp(COPY, _) -> v_cur2; + +v_orig_prt ->(0) o_cpy1(COPY, _) -> v_cur_tmp ->(0) o_get_cur -> v_cur1; + v_cur2 ->(1) o_get_cur; + +v_cur1 ->(1) o_store(STORE, _); +v_init_val ->(2) o_store; + +#0 -> (1) o_cond(INT_NOTEQUAL, _) -> vtmp2 -> (1) o_loop(CBRANCH, bb_precond); +v_elem_cnt ->(0) o_cpy(COPY, _) -> v_cnt_orig ->(0) o_cnt -> v_cnt ->(0) o_cond; + +bb_body ->(0) bb_precond; +bb_precond ->(1) bb_body + +-- +O_usercall(USERDEFINED BEFORE o_cpy); + +#76 ->>(0) O_usercall; +v_orig_prt ->>(1) O_usercall; +v_init_val ->> (2) O_usercall; +v_elem_cnt ->>(3) O_usercall; +v_elem_size ->>(4) O_usercall; + +DELETE o_store; + +#0 ->> (0) o_cpy; +#1 ->> (1) o_ptr_add + diff --git a/src/plugin/tests/fixtures/03_memset/target/memset.elf b/src/plugin/tests/fixtures/03_memset/target/memset.elf new file mode 100755 index 0000000000000000000000000000000000000000..0db178fab50b631257862384458b7b46d7d2678e GIT binary patch literal 16064 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 literal 0 HcmV?d00001 diff --git a/src/plugin/tests/fixtures/04_bitmap/approved/main.approved.txt b/src/plugin/tests/fixtures/04_bitmap/approved/main.approved.txt new file mode 100644 index 0000000..4097ad1 --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/approved/main.approved.txt @@ -0,0 +1,89 @@ + +uint main(int param_1,long param_2) + +{ + byte bVar1; + ulong uVar2; + ulong uVar3; + long lVar4; + ulong uVar5; + ulong uVar6; + ulong *puVar7; + long in_FS_OFFSET; + int local_184; + ulong local_180; + ulong local_158 [19]; + undefined8 local_c0; + ulong local_b8 [21]; + long local_10; + + local_10 = *(long *)(in_FS_OFFSET + 0x28); + puVar7 = local_158; + for (lVar4 = 0x14; lVar4 != 0; lVar4 = lVar4 + -1) { + *puVar7 = 0; + puVar7 = puVar7 + 1; + } + puVar7 = local_b8; + for (lVar4 = 0x14; lVar4 != 0; lVar4 = lVar4 + -1) { + *puVar7 = 0; + puVar7 = puVar7 + 1; + } + if (param_1 < 2) { + uVar2 = 0x29; + } + else { + uVar2 = strtoull(*(char **)(param_2 + 8),(char **)0x0,0); + } + if (param_1 < 3) { + uVar3 = 6; + } + else { + uVar3 = strtoull(*(char **)(param_2 + 0x10),(char **)0x0,0); + } + for (local_184 = 0; local_184 < 0x18; local_184 = local_184 + 1) { + uVar5 = ((long)local_184 * 0x13 + uVar2) % 0x500; + uVar6 = (uVar3 + uVar5 + 0xb) % 0x500; + vmsave(local_158,uVar5); + if ((((uint)uVar5 ^ (uint)uVar3) & 3) == 0) { + vmsave(local_b8,uVar6); + } + } + local_180 = uVar2 % 0x500; + unique0x10000534 = vmread(local_158,local_180); + bVar1 = (byte)local_180; + if (!unique0x10000534) { + vmsave(local_158,local_180); + local_180 = uVar3; + } + else { + vmclear(local_158,local_180); + } + uVar2 = (uVar2 * 7 + uVar3) % 0x500; + unique0x10000535 = vmread(local_b8,uVar2); + bVar1 = (byte)uVar2; + if (!unique0x10000535) { + if (vmread(local_158,uVar2)) { + vmsave(local_b8,uVar2); + local_180 = local_180 ^ uVar2 * 2; + } + } + else { + vmclear(local_b8,uVar2); + local_180 = local_180 + uVar2 * 3; + } + if ((uVar3 & 3) == 0) { + vmsave(local_158,local_180 % 0x500); + } + else if (vmread(local_158,uVar3 % 0x500)) { + local_180 = local_180 + 100; + } + printf("score=%llu users0=%llx locked3=%llx users19=%llx\n",local_180,local_158[0],local_b8[3], + local_c0); + if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { + /* WARNING: Subroutine does not return */ + __stack_chk_fail(); + } + return (uint)local_180 & 7; +} + + diff --git a/src/plugin/tests/fixtures/04_bitmap/rules/100_word b/src/plugin/tests/fixtures/04_bitmap/rules/100_word new file mode 100644 index 0000000..5401a09 --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/rules/100_word @@ -0,0 +1,6 @@ +v_bit-> (0) o_shift(INT_RIGHT, _) -> v_res; +#6 -> (1)o_shift +-- +#120 ->>(0) o_word(USERDEFINED BEFORE o_shift) ->> v_res; +v_bit ->>(1) o_word; +DELETE o_shift \ No newline at end of file diff --git a/src/plugin/tests/fixtures/04_bitmap/rules/200_shift b/src/plugin/tests/fixtures/04_bitmap/rules/200_shift new file mode 100644 index 0000000..1dbbf1a --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/rules/200_shift @@ -0,0 +1,7 @@ +#0 -> (1) o_to_byte(SUBPIECE, _); +v_bit ->(0) o_to_byte -> v_bit_1-> (0) o_and(INT_AND, _) -> v_res; +#0x3f -> (1)o_and +-- +#121 ->>(0) o_shift(USERDEFINED BEFORE o_and) ->> v_res; +v_bit ->>(1) o_shift; +DELETE o_and \ No newline at end of file diff --git a/src/plugin/tests/fixtures/04_bitmap/rules/300_mask b/src/plugin/tests/fixtures/04_bitmap/rules/300_mask new file mode 100644 index 0000000..bb9d4e7 --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/rules/300_mask @@ -0,0 +1,8 @@ +#1 -> (0) o_lft(INT_LEFT, _) -> v_res; +#121 ->(0) o_shift(USERDEFINED, _) -> v_shift_res -> (1)o_lft; +v_bit ->(1) o_shift + +-- +#117 ->>(0) o_mask(USERDEFINED BEFORE o_lft) ->> v_res; +v_bit ->>(1) o_mask; +DELETE o_lft diff --git a/src/plugin/tests/fixtures/04_bitmap/rules/330_mask_reorder_or b/src/plugin/tests/fixtures/04_bitmap/rules/330_mask_reorder_or new file mode 100644 index 0000000..710fb3b --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/rules/330_mask_reorder_or @@ -0,0 +1,8 @@ +#117 ->(0) o_mask(USERDEFINED, _) -> v_res ->(1) o_or(INT_OR, _); +v_other ->(0) o_or(INT_OR, _) + +-- + +v_other ->>(1) o_or; +v_res ->>(0) o_or + diff --git a/src/plugin/tests/fixtures/04_bitmap/rules/400_set b/src/plugin/tests/fixtures/04_bitmap/rules/400_set new file mode 100644 index 0000000..e482a26 --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/rules/400_set @@ -0,0 +1,17 @@ +#117 ->(0) o_mask(USERDEFINED,_) -> v_mask_res; +v_bit ->(1) o_mask; + + v_map ->(0) o_addr; +#0x78 ->(0) o_word(USERDEFINED, _) -> v_word_res ->(1) o_addr -> vtmp ->(1) o_load(LOAD, _)-> v_mask_map; +v_bit ->(1) o_word; + +v_mask_res ->(0) o_or(INT_OR, _); +v_mask_map ->(1) o_or -> v_or_res ->(2) o_finstore(STORE, _) +-- +#26 ->>(0) o_set(USERDEFINED BEFORE o_mask); +v_map ->>(1) o_set; +v_bit ->>(2) o_set; + +DELETE o_finstore + + diff --git a/src/plugin/tests/fixtures/04_bitmap/rules/410_set_alt b/src/plugin/tests/fixtures/04_bitmap/rules/410_set_alt new file mode 100644 index 0000000..8b20d09 --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/rules/410_set_alt @@ -0,0 +1,17 @@ +#117 ->(0) o_mask(USERDEFINED,_) -> v_mask_res; +v_bit1 ->(1) o_mask; + + v_map ->(0) o_addr; +#0x78 ->(0) o_word(USERDEFINED, _) -> v_word_res ->(1) o_addr -> vtmp ->(1) o_load(LOAD, _)-> v_mask_map; +v_bit ->(1) o_word; + +v_mask_res ->(0) o_or(INT_OR, _); +v_mask_map ->(1) o_or -> v_or_res ->(2) o_finstore(STORE, _) +-- +#26 ->>(0) o_set(USERDEFINED BEFORE o_mask); +v_map ->>(1) o_set; +v_bit ->>(2) o_set; + +DELETE o_finstore + + diff --git a/src/plugin/tests/fixtures/04_bitmap/rules/500_clear b/src/plugin/tests/fixtures/04_bitmap/rules/500_clear new file mode 100644 index 0000000..6c9ce9d --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/rules/500_clear @@ -0,0 +1,18 @@ +#117 ->(0) o_mask(USERDEFINED,_) -> v_mask_res ->(0) o_inv(INT_NEGATE, _) -> v_mask_neg; +v_bit ->(1) o_mask; + + v_map ->(0) o_addr; +#0x78 ->(0) o_word(USERDEFINED, _) -> v_word_res ->(1) o_addr -> vtmp ->(1) o_load(LOAD, _)-> v_mask_map; +v_bit ->(1) o_word; + +v_mask_map ->(0) o_and -> v_and_res ->(2) o_finstore(STORE, _); +v_mask_neg ->(1) o_and(INT_AND, _) + +-- +#30 ->>(0) o_set(USERDEFINED BEFORE o_mask); +v_map ->>(1) o_set; +v_bit ->>(2) o_set; + +DELETE o_finstore + + diff --git a/src/plugin/tests/fixtures/04_bitmap/rules/600_pre_test b/src/plugin/tests/fixtures/04_bitmap/rules/600_pre_test new file mode 100644 index 0000000..121b2dc --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/rules/600_pre_test @@ -0,0 +1,22 @@ + + v_map ->(0) o_addr; +#0x78 ->(0) o_word(USERDEFINED, _) -> v_word_res ->(1) o_addr -> vtmp ->(1) o_load(LOAD, _)-> v_mask_map; +v_bit ->(1) o_word; + + +#121 ->(0) o_shift(USERDEFINED, _) -> v_shift_res; +v_bit ->(1) o_shift; + +v_mask_map ->(0) o_right(INT_RIGHT, _) -> v_right_res; +v_shift_res ->(1) o_right; + +v_right_res ->(0) o_and(INT_AND, _) -> v_and_res ->(0) o_some; +#1 ->(1) o_and + + +-- +DELETE o_and; + +#33 ->>(0) o_pretest(USERDEFINED BEFORE o_word) ->> v_and_res; +v_map ->>(1) o_pretest; +v_bit ->>(2) o_pretest \ No newline at end of file diff --git a/src/plugin/tests/fixtures/04_bitmap/rules/600_pre_test_alt b/src/plugin/tests/fixtures/04_bitmap/rules/600_pre_test_alt new file mode 100644 index 0000000..30d55a0 --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/rules/600_pre_test_alt @@ -0,0 +1,22 @@ + + v_map ->(0) o_addr; +#0x78 ->(0) o_word(USERDEFINED, _) -> v_word_res ->(1) o_addr -> vtmp ->(1) o_load(LOAD, _)-> v_mask_map; +v_bit ->(1) o_word; + + +#121 ->(0) o_shift(USERDEFINED, _) -> v_shift_res; +v_bit1 ->(1) o_shift; + +v_mask_map ->(0) o_right(INT_RIGHT, _) -> v_right_res; +v_shift_res ->(1) o_right; + +v_right_res ->(0) o_and(INT_AND, _) -> v_and_res ->(0) o_some; +#1 ->(1) o_and + + +-- +DELETE o_and; + +#33 ->>(0) o_pretest(USERDEFINED BEFORE o_word) ->> v_and_res; +v_map ->>(1) o_pretest; +v_bit ->>(2) o_pretest \ No newline at end of file diff --git a/src/plugin/tests/fixtures/04_bitmap/rules/610_test b/src/plugin/tests/fixtures/04_bitmap/rules/610_test new file mode 100644 index 0000000..8a59340 --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/rules/610_test @@ -0,0 +1,17 @@ +#33 ->(0) o_pretest(USERDEFINED, _) -> v_pre_test_res; +v_map ->(1) o_pretest; +v_bit ->(2) o_pretest; + +v_pre_test_res ->(0) o_cond(INT_NOTEQUAL, _) -> v_cond_res; +#0 ->(1) o_cond + + +-- +#36 ->>(0) o_test(USERDEFINED BEFORE o_pretest) ->> v_cond_res; +v_map ->>(1) o_test; +v_bit ->>(2) o_test; + + + +DELETE o_cond + diff --git a/src/plugin/tests/fixtures/04_bitmap/rules/610_test_alt b/src/plugin/tests/fixtures/04_bitmap/rules/610_test_alt new file mode 100644 index 0000000..6073d61 --- /dev/null +++ b/src/plugin/tests/fixtures/04_bitmap/rules/610_test_alt @@ -0,0 +1,16 @@ +#33 ->(0) o_pretest(USERDEFINED, _) -> v_pre_test_res; +v_map ->(1) o_pretest; +v_bit ->(2) o_pretest; + +v_pre_test_res ->(0) o_cond(INT_EQUAL, _) -> v_cond_res; +#0 ->(1) o_cond + + +-- +#36 ->>(0) o_test(USERDEFINED AFTER o_pretest) ->> v_test_res ->>(0) o_inv(BOOL_NEGATE AFTER o_pretest) ->> v_cond_res; +v_map ->>(1) o_test; +v_bit ->>(2) o_test; + + +DELETE o_cond + diff --git a/src/plugin/tests/fixtures/04_bitmap/target/bitmap.elf b/src/plugin/tests/fixtures/04_bitmap/target/bitmap.elf new file mode 100755 index 0000000000000000000000000000000000000000..acf1049efb758dff9e94bc8468857775f88120bf GIT binary patch literal 16056 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 z zS-&O0qa}pc%Q{q0)}2r>g?zZn_d(E_PV8kJCn(Pt_rjjmh(gOcQ82=ddE;lc z8bXC~D)zE&6&ztjY2VxbpR)Z1){}Lxpmy0)&b;=&1dnne{!7mhexAtt0lP7=N}cc* z__*yuY$q5YC0CKhl;8u9x$VEl0zuIe7eWgTd+d8yAXqPkjAAGFh{ygA3j|ltz`2Up z3G0ujxZ{`gj-b4MiN5#xd7ABI{8flG8LwheK*mq#=TV{d#lF%xO40YW|BA=HC*)`f z{zeQLz3sma{sMgDeMjCa<(#EgUueOTu&s94%ldn`4ono$bEq@4@c#<|&0T3<*2Qve zR?f%DFp8aw Date: Sat, 30 May 2026 03:23:10 +0300 Subject: [PATCH 9/9] chore: add testing to ci --- .github/workflows/build-and-test.yml | 85 ++++++++++++++++++++++++++++ .github/workflows/build.yml | 41 -------------- README.md | 3 + 3 files changed, 88 insertions(+), 41 deletions(-) create mode 100644 .github/workflows/build-and-test.yml delete mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 0000000..05bee5d --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,85 @@ +name: build and test + +on: [pull_request] + +jobs: + test-compiler: + name: Test Compiler + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y bison flex libfl-dev g++-13 python3-venv + g++-13 --version + python3 -m venv venv + . venv/bin/activate + python -m pip install --upgrade pip + python -m pip install 'meson>=1.10.1' 'ninja>=1.11' 'reoxide==0.7.2' + + - name: Test compiler + working-directory: src/compiler + run: | + . ../../venv/bin/activate + export XDG_CONFIG_HOME="${RUNNER_TEMP}/config" + mkdir -p "${XDG_CONFIG_HOME}/reoxide" + touch "${XDG_CONFIG_HOME}/reoxide/reoxide.toml" + CXX=g++-13 meson setup build --buildtype release -Dtests=true + meson compile -j 1 -C build + meson test -C build --print-errorlogs + + build-plugin: + name: Build Plugin + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - name: Build plugin + run: docker build -o tmp/out . + + test-plugin: + name: Test Plugin + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - name: Install host dependencies + run: | + sudo apt-get update + sudo apt-get install -y bison flex libfl-dev g++-13 python3-venv + python3 -m venv venv + . venv/bin/activate + python -m pip install --upgrade pip + python -m pip install 'meson>=1.10.1' 'ninja>=1.11' 'reoxide==0.7.2' + + - name: Build compiler for rule fixtures + working-directory: src/compiler + run: | + . ../../venv/bin/activate + export XDG_CONFIG_HOME="${RUNNER_TEMP}/config" + mkdir -p "${XDG_CONFIG_HOME}/reoxide" + touch "${XDG_CONFIG_HOME}/reoxide/reoxide.toml" + CXX=g++-13 meson setup build --buildtype release -Dtests=false + meson compile -j 1 -C build + + - name: Build plugin test base image + run: | + docker build \ + -f src/plugin/tests/docker/base.Dockerfile \ + -t pcode-weaver-plugin-test-base:ghidra-12.0_reoxide-0.7.2 \ + . + + - name: Build plugin test image + run: docker build --target plugin-test -t pcode-weaver-plugin-test . + + - name: Test plugin + working-directory: src/plugin/tests + run: | + . ../../../venv/bin/activate + meson setup build --buildtype release + meson test -C build --print-errorlogs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index e3e1840..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: build - -on: [pull_request] - -jobs: - build-compiler: - name: Build Compiler - runs-on: ubuntu-24.04 - - steps: - - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y bison flex libfl-dev g++-13 python3-venv - g++-13 --version - python3 -m venv venv - . venv/bin/activate - python -m pip install --upgrade pip - python -m pip install 'meson>=1.10.1' 'ninja>=1.11' 'reoxide==0.7.2' - - - name: Build compiler - working-directory: src/compiler - run: | - . ../../venv/bin/activate - export XDG_CONFIG_HOME="${RUNNER_TEMP}/config" - mkdir -p "${XDG_CONFIG_HOME}/reoxide" - touch "${XDG_CONFIG_HOME}/reoxide/reoxide.toml" - CXX=g++-13 meson setup build --buildtype release - meson compile -j 1 -C build - - build-plugin: - name: Build Plugin - runs-on: ubuntu-22.04 - - steps: - - uses: actions/checkout@v4 - - - name: Build plugin - run: docker build -o tmp/out . diff --git a/README.md b/README.md index 26183eb..8fd08ed 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # Pcode Weaver +[![build and test](https://github.com/osogi/pcode-weaver/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/osogi/pcode-weaver/actions/workflows/build-and-test.yml) +[![formatting-check](https://github.com/osogi/pcode-weaver/actions/workflows/formatting-check.yml/badge.svg)](https://github.com/osogi/pcode-weaver/actions/workflows/formatting-check.yml) + Experimental ReOxide(Ghidra) plugin for applying custom p-code rewrite rules with validation checks.