Commit ff48a66b authored by nagayama15's avatar nagayama15

Implement the watermarker using operands swapping method

parent 0d6a8dfd
...@@ -423,13 +423,25 @@ namespace kyut::watermarker { ...@@ -423,13 +423,25 @@ namespace kyut::watermarker {
return (std::max)(embedExpression(expr.left, stream), embedExpression(expr.right, stream)); return (std::max)(embedExpression(expr.left, stream), embedExpression(expr.right, stream));
} }
// TODO: implement watermarking // Sort both of the operands
const auto leftSideEffect = embedExpression(expr.left, stream); auto [lo, hi] = std::minmax(expr.left, expr.right, [](auto a, auto b) { return *a < *b; });
const auto rightSideEffect = embedExpression(expr.right, stream);
(void)swapOperands; const auto loEffect = embedExpression(lo, stream);
const auto hiEffect = embedExpression(hi, stream);
return (std::max)(leftSideEffect, rightSideEffect); if (static_cast<std::uint32_t>(loEffect) + static_cast<std::uint32_t>(hiEffect) >= 3) {
// The operands have side effect and cannot be swapped
return (std::max)(loEffect, hiEffect);
}
// Embed watermarks by swapping operands
const bool bit = stream.readBit();
if (bit == (expr.left == lo)) {
swapOperands(expr);
}
return (std::max)(loEffect, hiEffect);
} }
SideEffect embedSelect(wasm::Select &expr, CircularBitStreamReader &stream) { SideEffect embedSelect(wasm::Select &expr, CircularBitStreamReader &stream) {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
BOOST_AUTO_TEST_SUITE(kyut) BOOST_AUTO_TEST_SUITE(kyut)
BOOST_AUTO_TEST_SUITE(watermarker) BOOST_AUTO_TEST_SUITE(watermarker)
BOOST_AUTO_TEST_CASE(embed_operand_swapping) { BOOST_AUTO_TEST_CASE(embed_operand_swapping_000000) {
wasm::Module module; wasm::Module module;
wasm::ModuleReader{}.read(KYUT_TEST_SOURCE_DIR "/example/test2.wast", module); wasm::ModuleReader{}.read(KYUT_TEST_SOURCE_DIR "/example/test2.wast", module);
...@@ -24,24 +24,117 @@ BOOST_AUTO_TEST_CASE(embed_operand_swapping) { ...@@ -24,24 +24,117 @@ BOOST_AUTO_TEST_CASE(embed_operand_swapping) {
BOOST_REQUIRE_EQUAL(module.functions[2]->name, "f3"); BOOST_REQUIRE_EQUAL(module.functions[2]->name, "f3");
// Embed 0b0000'00 // Embed 0b0000'00
CircularBitStreamReader s{{0b0000'0000}};
const auto numBitsEmbedded = embedOperandSwapping(module, s);
BOOST_REQUIRE_EQUAL(numBitsEmbedded, std::size_t{6});
BOOST_REQUIRE_EQUAL(module.functions.size(), std::size_t{3});
BOOST_REQUIRE_EQUAL(module.functions[0]->name, "f1");
BOOST_REQUIRE_EQUAL(module.functions[1]->name, "f2");
BOOST_REQUIRE_EQUAL(module.functions[2]->name, "f3");
// f1
{
const auto body = module.functions[0]->body->cast<wasm::Binary>();
BOOST_REQUIRE_EQUAL(body->op, wasm::AddInt32);
BOOST_REQUIRE_EQUAL(body->left->cast<wasm::Const>()->value.geti32(), 1);
BOOST_REQUIRE_EQUAL(body->right->cast<wasm::Const>()->value.geti32(), 2);
}
// f2
{
const auto body = module.functions[1]->body->cast<wasm::Binary>();
BOOST_REQUIRE_EQUAL(body->op, wasm::AddInt32);
BOOST_REQUIRE_EQUAL(body->left->cast<wasm::Const>()->value.geti32(), 3);
const auto r = body->right->cast<wasm::Binary>();
BOOST_REQUIRE_EQUAL(r->op, wasm::AddInt32);
BOOST_REQUIRE_EQUAL(r->left->cast<wasm::Const>()->value.geti32(), 1);
BOOST_REQUIRE_EQUAL(r->right->cast<wasm::Const>()->value.geti32(), 2);
}
// f3
{
const auto body = module.functions[2]->body->cast<wasm::Binary>();
BOOST_REQUIRE_EQUAL(body->op, wasm::AddInt32);
BOOST_REQUIRE_EQUAL(body->left->is<wasm::Binary>(), true);
BOOST_REQUIRE_EQUAL(body->right->is<wasm::Binary>(), true);
const auto l = body->left->cast<wasm::Binary>();
const auto r = body->right->cast<wasm::Binary>();
BOOST_REQUIRE_EQUAL(l->op, wasm::AddInt32);
BOOST_REQUIRE_EQUAL(l->left->cast<wasm::Const>()->value.geti32(), 1);
BOOST_REQUIRE_EQUAL(l->right->cast<wasm::Const>()->value.geti32(), 2);
BOOST_REQUIRE_EQUAL(r->op, wasm::GtSInt32);
BOOST_REQUIRE_EQUAL(r->left->cast<wasm::Const>()->value.geti32(), 3);
BOOST_REQUIRE_EQUAL(r->right->cast<wasm::Const>()->value.geti32(), 4);
}
}
BOOST_AUTO_TEST_CASE(embed_operand_swapping_110111) {
wasm::Module module;
wasm::ModuleReader{}.read(KYUT_TEST_SOURCE_DIR "/example/test2.wast", module);
BOOST_REQUIRE_EQUAL(module.functions.size(), std::size_t{3});
BOOST_REQUIRE_EQUAL(module.functions[0]->name, "f1");
BOOST_REQUIRE_EQUAL(module.functions[1]->name, "f2");
BOOST_REQUIRE_EQUAL(module.functions[2]->name, "f3");
// Embed 0b1101'11
CircularBitStreamReader s{{0b1101'1100}};
const auto numBitsEmbedded = embedOperandSwapping(module, s);
BOOST_REQUIRE_EQUAL(numBitsEmbedded, std::size_t{6});
BOOST_REQUIRE_EQUAL(module.functions.size(), std::size_t{3});
BOOST_REQUIRE_EQUAL(module.functions[0]->name, "f1");
BOOST_REQUIRE_EQUAL(module.functions[1]->name, "f2");
BOOST_REQUIRE_EQUAL(module.functions[2]->name, "f3");
// f1
{ {
CircularBitStreamReader s{{0b0000'0000}}; const auto body = module.functions[0]->body->cast<wasm::Binary>();
const auto numBitsEmbedded = embedOperandSwapping(module, s);
BOOST_REQUIRE_EQUAL(body->op, wasm::AddInt32);
BOOST_REQUIRE_EQUAL(numBitsEmbedded, std::size_t{6}); BOOST_REQUIRE_EQUAL(body->left->cast<wasm::Const>()->value.geti32(), 2);
BOOST_REQUIRE_EQUAL(module.functions.size(), std::size_t{3}); BOOST_REQUIRE_EQUAL(body->right->cast<wasm::Const>()->value.geti32(), 1);
BOOST_REQUIRE_EQUAL(module.functions[0]->name, "f1"); }
BOOST_REQUIRE_EQUAL(module.functions[1]->name, "f2"); // f2
BOOST_REQUIRE_EQUAL(module.functions[2]->name, "f3"); {
const auto body = module.functions[1]->body->cast<wasm::Binary>();
// f1
{ BOOST_REQUIRE_EQUAL(body->op, wasm::AddInt32);
const auto bin = module.functions[0]->body->cast<wasm::Binary>(); BOOST_REQUIRE_EQUAL(body->left->cast<wasm::Const>()->value.geti32(), 3);
BOOST_REQUIRE_EQUAL(bin->left->cast<wasm::Const>()->value.geti32(), 1); const auto r = body->right->cast<wasm::Binary>();
BOOST_REQUIRE_EQUAL(bin->right->cast<wasm::Const>()->value.geti32(), 2);
} BOOST_REQUIRE_EQUAL(r->op, wasm::AddInt32);
BOOST_REQUIRE_EQUAL(r->left->cast<wasm::Const>()->value.geti32(), 2);
BOOST_REQUIRE_EQUAL(r->right->cast<wasm::Const>()->value.geti32(), 1);
}
// f3
{
const auto body = module.functions[2]->body->cast<wasm::Binary>();
BOOST_REQUIRE_EQUAL(body->op, wasm::AddInt32);
BOOST_REQUIRE_EQUAL(body->left->is<wasm::Binary>(), true);
BOOST_REQUIRE_EQUAL(body->right->is<wasm::Binary>(), true);
const auto l = body->left->cast<wasm::Binary>();
const auto r = body->right->cast<wasm::Binary>();
BOOST_REQUIRE_EQUAL(l->op, wasm::LtSInt32);
BOOST_REQUIRE_EQUAL(l->left->cast<wasm::Const>()->value.geti32(), 4);
BOOST_REQUIRE_EQUAL(l->right->cast<wasm::Const>()->value.geti32(), 3);
BOOST_REQUIRE_EQUAL(r->op, wasm::AddInt32);
BOOST_REQUIRE_EQUAL(r->left->cast<wasm::Const>()->value.geti32(), 2);
BOOST_REQUIRE_EQUAL(r->right->cast<wasm::Const>()->value.geti32(), 1);
} }
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment