Skip to content

Commit

Permalink
Merge pull request #1564 from MoarVM/fix_mixin_repossession
Browse files Browse the repository at this point in the history
Fix memory corruption caused by repossessed mixins losing their repla…
  • Loading branch information
niner committed Oct 15, 2021
2 parents f7d6bc6 + c7be428 commit 24fd304
Showing 1 changed file with 31 additions and 23 deletions.
54 changes: 31 additions & 23 deletions src/6model/reprs/P6opaque.c
Expand Up @@ -141,7 +141,9 @@ static void gc_free(MVMThreadContext *tc, MVMObject *obj) {
}

/* If we replaced the object body, free the replacement. */
MVM_free(((MVMP6opaque *)obj)->body.replaced);
void *replaced = ((MVMP6opaque *)obj)->body.replaced;
if (replaced)
MVM_fixed_size_free(tc, tc->instance->fsa, STABLE(obj)->size - sizeof(MVMObject), replaced);
}

/* Marks the representation data in an STable.*/
Expand Down Expand Up @@ -1234,11 +1236,38 @@ static void deserialize_repr_data(MVMThreadContext *tc, MVMSTable *st, MVMSerial
st->REPR_data = repr_data;
}

static void allocate_replaced_body(MVMThreadContext *tc, MVMObject *obj, MVMSTable *new_type) {
/* Get current object body. */
MVMP6opaqueBody *body = (MVMP6opaqueBody *)OBJECT_BODY(obj);
void *old = body->replaced ? body->replaced : body;

/* Allocate new memory. */
size_t new_size = new_type->size - sizeof(MVMObject);
size_t old_size = STABLE(obj)->size - sizeof(MVMObject);
void *new = MVM_fixed_size_alloc_zeroed(tc, tc->instance->fsa, new_size);

/* Copy existing to new.
* XXX Need more care here, as may have to re-barrier pointers. */
memcpy(new, old, old_size);

/* Pointer switch, taking care of existing body issues. */
if (body->replaced) {
body->replaced = new;
MVM_fixed_size_free_at_safepoint(tc, tc->instance->fsa, old_size, old);
}
else {
body->replaced = new;
}
}

/* Deserializes the data. */
static void deserialize(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data, MVMSerializationReader *reader) {
MVMP6opaqueREPRData *repr_data = (MVMP6opaqueREPRData *)st->REPR_data;
MVMuint16 num_attributes = repr_data->num_attributes;
MVMuint16 i;
if (root->header.size != st->size && !((MVMP6opaque*)root)->body.replaced) {
allocate_replaced_body(tc, root, st);
}
data = MVM_p6opaque_real_data(tc, data);
for (i = 0; i < num_attributes; i++) {
MVMuint16 a_offset = repr_data->attribute_offsets[i];
Expand Down Expand Up @@ -1322,28 +1351,7 @@ static void change_type(MVMThreadContext *tc, MVMObject *obj, MVMObject *new_typ

/* Resize if needed. */
if (STABLE(obj)->size != STABLE(new_type)->size) {
/* Get current object body. */
MVMP6opaqueBody *body = (MVMP6opaqueBody *)OBJECT_BODY(obj);
void *old = body->replaced ? body->replaced : body;

/* Allocate new memory. */
size_t new_size = STABLE(new_type)->size - sizeof(MVMObject);
void *new = MVM_malloc(new_size);
memset((char *)new + (STABLE(obj)->size - sizeof(MVMObject)),
0, new_size - (STABLE(obj)->size - sizeof(MVMObject)));

/* Copy existing to new.
* XXX Need more care here, as may have to re-barrier pointers. */
memcpy(new, old, STABLE(obj)->size - sizeof(MVMObject));

/* Pointer switch, taking care of existing body issues. */
if (body->replaced) {
body->replaced = new;
MVM_free(old);
}
else {
body->replaced = new;
}
allocate_replaced_body(tc, obj, STABLE(new_type));
}

/* Finally, ready to switch over the STable. */
Expand Down

0 comments on commit 24fd304

Please sign in to comment.