8302594: use-after-free in Node::destruct

Reviewed-by: kvn, thartmann
This commit is contained in:
Justin King 2023-02-16 14:14:46 +00:00 committed by Tobias Hartmann
parent 9b911b492f
commit 2e3cea01da

View File

@ -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-------------------------------------------