From 249df145f5acdb134af6cc1bb935af8f49b75a0f Mon Sep 17 00:00:00 2001 From: IgorYbema Date: Sun, 10 May 2026 09:25:42 +0000 Subject: [PATCH 1/2] Fix loop1 using SETVAL variable index as virtual slot in inner scan In bc_assign_slots loop1, SETVAL's 'a' field is a variable index (e.g. 3), not a virtual slot number. When SETVAL appeared as an outer node in the middle of a range, its inner scan propagated that variable index to other nodes (NE's c/a fields) that coincidentally held the same value. This corrupted the virtual slot normalization so that NE and a GETVAL both ended up mapped to the same heap slot, leaving NE's 'b' operand unmapped (positive). Skip the inner scan for SETVAL so its variable index is never used as a virtual slot reference. Co-Authored-By: Claude Sonnet 4.6 --- HeishaMon/src/rules/rules.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/HeishaMon/src/rules/rules.cpp b/HeishaMon/src/rules/rules.cpp index 5ef8cf7d..26975130 100644 --- a/HeishaMon/src/rules/rules.cpp +++ b/HeishaMon/src/rules/rules.cpp @@ -2124,6 +2124,10 @@ static void bc_assign_slots(struct rules_t *obj) { setval(x->a, vars); } + if(gettype(obj->bc.buffer[a]) == OP_SETVAL) { + continue; + } + for(c=a;c<=end;c = bc_next(obj, c)) { if(c == -1) { break; From 5556504925a765b48b55a2bc3cd9c391bae30044 Mon Sep 17 00:00:00 2001 From: IgorYbema Date: Mon, 18 May 2026 14:40:02 +0000 Subject: [PATCH 2/2] merge with origin --- HeishaMon/src/rules/rules.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/HeishaMon/src/rules/rules.cpp b/HeishaMon/src/rules/rules.cpp index 26975130..ebccb449 100644 --- a/HeishaMon/src/rules/rules.cpp +++ b/HeishaMon/src/rules/rules.cpp @@ -2099,7 +2099,12 @@ static void bc_assign_slots(struct rules_t *obj) { (gettype(obj->bc.buffer[a]) == OP_PUSH && (d < 0 || d >= min))) { continue; } - + if(gettype(obj->bc.buffer[a]) == OP_CALL && getval(x->a) == 0) { + continue; + } + if(gettype(obj->bc.buffer[a]) == OP_SETVAL) { + continue; + } int32_t e = bc_before(a); struct vm_top_t *z = NULL; @@ -2124,10 +2129,6 @@ static void bc_assign_slots(struct rules_t *obj) { setval(x->a, vars); } - if(gettype(obj->bc.buffer[a]) == OP_SETVAL) { - continue; - } - for(c=a;c<=end;c = bc_next(obj, c)) { if(c == -1) { break; @@ -3331,7 +3332,11 @@ static int16_t rule_create(char **text, struct rules_t *obj) { switch(type) { case TSEMICOLON: { - bc_parent(obj, OP_CLEAR, 0, 0, 0); + uint16_t a = bc_parent(obj, OP_CLEAR, 0, 0, 0); + { + struct vm_top_t *node = (struct vm_top_t *)&obj->bc.buffer[bc_before(a)]; + setval(node->a, 0); + } pos++; if(lexer_peek(text, pos, &type, &start, &len) <= 0) { @@ -4945,7 +4950,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { uint16_t c = (int8_t)getval(node->c); #if defined(DEBUG) || defined(COVERALLS) - if((int8_t)getval(node->a) >= 0) { + if((int8_t)getval(node->a) > 0) { logprintf_P(F("FATAL: Internal error in %s #%d pos (%d)"), __FUNCTION__, __LINE__, pos/4); return -1; } @@ -4970,7 +4975,7 @@ int8_t rule_run(struct rules_t *obj, uint8_t validate) { return -1; /* LCOV_EXCL_STOP*/ } - if(rules_gettop() == 1) { + if(rules_gettop() == 1 && a != 4) { switch(rules_type(-1)) { case VNULL: { struct vm_vnull_t *upd = (struct vm_vnull_t *)&obj->heap->buffer[a];