Gordon Henriksen <[EMAIL PROTECTED]> wrote:
... Best example: morph. morph must die.
Morph is necessary. But please note: morph changes the vtable of the PMC to point to the new data types table. It has nothing to do with a typed union.
The vtable IS the discriminator. I'm referring to this:
typedef union UnionVal {
struct { /* Buffers structure */
void * bufstart;
size_t buflen;
} b;
struct { /* PMC unionval members */
DPOINTER* _struct_val; /* two ptrs, both are defines */
PMC* _pmc_val;
} ptrs;
INTVAL int_val;
FLOATVAL num_val;
struct parrot_string_t * string_val;
} UnionVal;So long as the discriminator does not change, the union is type stable. When the discriminator does change, as per here:
void
Parrot_PerlInt_set_string_native(Parrot_Interp interpreter, PMC* pmc, STRING* value)
{
VTABLE_morph(interpreter, pmc, enum_class_PerlString);
VTABLE_set_string_native(interpreter, pmc, value);
}
void
Parrot_perlscalar_morph(Parrot_Interp interpreter, PMC* pmc, INTVAL type)
{
if (pmc->vtable->base_type == enum_class_PerlString) {
if (type == enum_class_PerlString)
return;
PObj_custom_mark_CLEAR(pmc);
pmc->vtable = Parrot_base_vtables[type];
return;
}
if (type == enum_class_PerlString) {
pmc->vtable = Parrot_base_vtables[type];
VTABLE_init(interpreter, pmc);
return;
}
PObj_custom_mark_CLEAR(pmc);
pmc->vtable = Parrot_base_vtables[type];
}
... then these can both run:
Parrot_scalar_get_string(Parrot_Interp interpreter, PMC* pmc)
{
return (STRING*)pmc->cache.string_val;
}
FLOATVAL
Parrot_scalar_get_number(Parrot_Interp interpreter, PMC* pmc)
{
return pmc->cache.num_val;
}That clearly allows a struct parrot_string_t * to freely share the same memory as a double. Were it an int and a double, the "surprising results" from this unprotected access wouldn't violate the no crashes guarantee. But it's a pointer! Dereferencing it could cause a segfault, or a read or write of an arbitrary memory location. Both clearly violate the crucial guarantee.
—
Gordon Henriksen [EMAIL PROTECTED]
