Fixed access-after-delete bug in mem2reg code
authorClifford Wolf <clifford@clifford.at>
Fri, 27 May 2016 15:25:33 +0000 (17:25 +0200)
committerClifford Wolf <clifford@clifford.at>
Fri, 27 May 2016 15:25:33 +0000 (17:25 +0200)
frontends/ast/ast.h
frontends/ast/simplify.cc

index b4e58d79f31e2e3dde8545afb9f851a4cd495a7c..21c3ba3c6526082cd148cc908981ec10f4730150 100644 (file)
@@ -219,6 +219,7 @@ namespace AST
                                dict<AstNode*, uint32_t> &mem2reg_flags, dict<AstNode*, uint32_t> &proc_flags, uint32_t &status_flags);
                bool mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block);
                bool mem2reg_check(pool<AstNode*> &mem2reg_set);
+               void mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes);
                void meminfo(int &mem_width, int &mem_size, int &addr_bits);
 
                // additional functionality for evaluating constant functions
index e000872802784c6350cd62a2cfd845a863134daf..c09b912c2797caa7339526d62f9348a21e4a4ab8 100644 (file)
@@ -150,12 +150,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
 
                        while (mem2reg_as_needed_pass2(mem2reg_set, this, NULL)) { }
 
-                       for (size_t i = 0; i < children.size(); i++) {
-                               if (mem2reg_set.count(children[i]) > 0) {
-                                       delete children[i];
-                                       children.erase(children.begin() + (i--));
-                               }
-                       }
+                       vector<AstNode*> delnodes;
+                       mem2reg_remove(mem2reg_set, delnodes);
+
+                       for (auto node : delnodes)
+                               delete node;
                }
 
                while (simplify(const_fold, at_zero, in_lvalue, 2, width_hint, sign_hint, in_param)) { }
@@ -2606,6 +2605,23 @@ bool AstNode::mem2reg_check(pool<AstNode*> &mem2reg_set)
        return true;
 }
 
+void AstNode::mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes)
+{
+       log_assert(mem2reg_set.count(this) == 0);
+
+       if (mem2reg_set.count(id2ast))
+               id2ast = nullptr;
+
+       for (size_t i = 0; i < children.size(); i++) {
+               if (mem2reg_set.count(children[i]) > 0) {
+                       delnodes.push_back(children[i]);
+                       children.erase(children.begin() + (i--));
+               } else {
+                       children[i]->mem2reg_remove(mem2reg_set, delnodes);
+               }
+       }
+}
+
 // actually replace memories with registers
 bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block)
 {