From fcd422da463555bcd6392bba11fd7d0820831783 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Tue, 4 Apr 2023 12:52:23 +0000 Subject: [PATCH] 8302594: use-after-free in Node::destruct Backport-of: 2e3cea01daca594dfa4477439a9849eea19b249e --- src/hotspot/share/opto/node.cpp | 58 ++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index 4790d1b010d..b65bfc8e330 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -616,33 +616,7 @@ void Node::destruct(PhaseValues* phase) { //assert(def->out(def->outcnt()-1) == (Node *)this,"bad def-use hacking in reclaim"); } assert(outcnt() == 0, "deleting a node must not leave a dangling use"); - // See if the input array was allocated just prior to the object - int edge_size = _max*sizeof(void*); - int out_edge_size = _outmax*sizeof(void*); - char *edge_end = ((char*)_in) + edge_size; - char *out_array = (char*)(_out == NO_OUT_ARRAY? NULL: _out); - int node_size = size_of(); - // Free the output edge array - if (out_edge_size > 0) { - compile->node_arena()->Afree(out_array, out_edge_size); - } - - // Free the input edge array and the node itself - if( edge_end == (char*)this ) { - // It was; free the input array and object all in one hit -#ifndef ASSERT - compile->node_arena()->Afree(_in,edge_size+node_size); -#endif - } else { - // Free just the input array - compile->node_arena()->Afree(_in,edge_size); - - // Free just the object -#ifndef ASSERT - compile->node_arena()->Afree(this,node_size); -#endif - } if (is_macro()) { compile->remove_macro_node(this); } @@ -665,13 +639,43 @@ void Node::destruct(PhaseValues* phase) { } BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); bs->unregister_potential_barrier_node(this); + + // See if the input array was allocated just prior to the object + int edge_size = _max*sizeof(void*); + int out_edge_size = _outmax*sizeof(void*); + char *in_array = ((char*)_in); + char *edge_end = in_array + edge_size; + char *out_array = (char*)(_out == NO_OUT_ARRAY? NULL: _out); + int node_size = size_of(); + #ifdef ASSERT // We will not actually delete the storage, but we'll make the node unusable. + compile->remove_modified_node(this); *(address*)this = badAddress; // smash the C++ vtbl, probably _in = _out = (Node**) badAddress; _max = _cnt = _outmax = _outcnt = 0; - compile->remove_modified_node(this); #endif + + // Free the output edge array + if (out_edge_size > 0) { + compile->node_arena()->Afree(out_array, out_edge_size); + } + + // Free the input edge array and the node itself + if( edge_end == (char*)this ) { + // It was; free the input array and object all in one hit +#ifndef ASSERT + compile->node_arena()->Afree(in_array, edge_size+node_size); +#endif + } else { + // Free just the input array + compile->node_arena()->Afree(in_array, edge_size); + + // Free just the object +#ifndef ASSERT + compile->node_arena()->Afree(this, node_size); +#endif + } } //------------------------------grow-------------------------------------------