Merge remote-tracking branch 'origin/topic/vern/zam-degenerate-CFT-propagation'

* origin/topic/vern/zam-degenerate-CFT-propagation:
  fixes for ZAM's propagation of control flow information for some degenerate constructs
This commit is contained in:
Arne Welzel 2024-11-08 15:35:00 +01:00
commit 4f8ef3c792
8 changed files with 77 additions and 4 deletions

View file

@ -1,3 +1,7 @@
7.1.0-dev.475 | 2024-11-08 15:35:00 +0100
* fixes for ZAM's propagation of control flow information for some degenerate constructs (Vern Paxson, Corelight)
7.1.0-dev.473 | 2024-11-08 15:31:39 +0100 7.1.0-dev.473 | 2024-11-08 15:31:39 +0100
* fixed ZAM memory leak when looping over vectors of records (Vern Paxson, Corelight) * fixed ZAM memory leak when looping over vectors of records (Vern Paxson, Corelight)

View file

@ -1 +1 @@
7.1.0-dev.473 7.1.0-dev.475

View file

@ -1020,8 +1020,11 @@ void ZAMCompiler::BackPropagateCFT(int inst_num, ControlFlowType cf_type) {
if ( insts1[j]->live ) if ( insts1[j]->live )
break; break;
// We should never wind up killing an instruction that has no predecessor. // Initializations of unused variables in functions with no arguments can
ASSERT(j >= 0); // come at the very beginning of the function, in which case there will
// be no predecessor to back-propagate to.
if ( j < 0 )
return;
// Make sure the CFT entry is created. // Make sure the CFT entry is created.
AddCFT(insts1[j], cf_type); AddCFT(insts1[j], cf_type);

View file

@ -154,7 +154,11 @@ const ZAMStmt ZAMCompiler::IfElse(const Expr* e, const Stmt* s1, const Stmt* s2)
SetV(cond_stmt, GoToTargetBeyond(branch_after_s1), branch_v); SetV(cond_stmt, GoToTargetBeyond(branch_after_s1), branch_v);
SetGoTo(branch_after_s1, GoToTargetBeyond(s2_end)); SetGoTo(branch_after_s1, GoToTargetBeyond(s2_end));
AddCFT(insts1[else_start], CFT_ELSE);
if ( else_start < insts1.size() )
// There was a non-empty else branch.
AddCFT(insts1[else_start], CFT_ELSE);
AddCFT(insts1.back(), CFT_BLOCK_END); AddCFT(insts1.back(), CFT_BLOCK_END);
return s2_end; return s2_end;
@ -848,6 +852,11 @@ const ZAMStmt ZAMCompiler::Loop(const Stmt* body) {
auto head = StartingBlock(); auto head = StartingBlock();
auto b = CompileStmt(body); auto b = CompileStmt(body);
if ( head.stmt_num == static_cast<int>(insts1.size()) ) {
reporter->Error("infinite empty loop: %s", obj_desc(body).c_str());
return head;
}
AddCFT(insts1[head.stmt_num], CFT_LOOP); AddCFT(insts1[head.stmt_num], CFT_LOOP);
AddCFT(insts1[b.stmt_num], CFT_LOOP_END); AddCFT(insts1[b.stmt_num], CFT_LOOP_END);

View file

@ -0,0 +1,3 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
error: infinite empty loop: ; <...>/infinite-empty-loop.zeek, line 13
fatal error: Optimized script execution aborted due to errors

View file

@ -0,0 +1,4 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
got through the conditional #1
got through the conditional #2
got through the conditional #3

View file

@ -0,0 +1,14 @@
# @TEST-DOC: Regression tests for past ZAM bugs handling empty infinite loops
# @TEST-REQUIRES: test "${ZEEK_USE_CPP}" != "1"
#
# @TEST-EXEC-FAIL: zeek -b -O ZAM %INPUT
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff .stderr
event zeek_init()
{
# It used to be that ZAM would fault doing control-flow propagation
# when compiling empty infinite loops. Now it should generate a
# compile-time error.
while ( T )
;
}

View file

@ -0,0 +1,36 @@
# @TEST-DOC: Regression tests for past ZAM bugs inlining empty functions
# @TEST-REQUIRES: test "${ZEEK_USE_CPP}" != "1"
#
# @TEST-EXEC: zeek -b -O ZAM %INPUT >output
# @TEST-EXEC: btest-diff output
function empty_func1() { }
function empty_func2() { local i: int; }
function empty_func3() { local i = 1; }
# Use a global to avoid constant propagation optimizing out the conditional.
global bar = F;
event zeek_init()
{
if ( bar )
empty_func1();
else
empty_func1();
print "got through the conditional #1";
if ( bar )
empty_func2();
else
empty_func2();
print "got through the conditional #2";
if ( bar )
empty_func3();
else
empty_func3();
print "got through the conditional #3";
}