solstice

Compute collected power and efficiencies of a solar plant
git clone git://git.meso-star.com/solstice.git
Log | Files | Refs | README | LICENSE

commit 0322d4655f83900a1ac53e2b3c4e0e301b3cae4d
parent 33774c2cf3ed725c6c545612608d1a496de8bb02
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 23 Nov 2016 15:29:30 +0100

Fix a memory corruption in the parsing of the entity

Diffstat:
Msrc/parser/solstice_entity.h | 23+++++++++++++++++++++++
Msrc/parser/solstice_parser.c | 40++++++++++++++++++++++++++--------------
2 files changed, 49 insertions(+), 14 deletions(-)

diff --git a/src/parser/solstice_entity.h b/src/parser/solstice_entity.h @@ -146,6 +146,29 @@ solstice_entity_copy_and_release return RES_OK; } +static INLINE res_T +solstice_entity_copy_and_clear + (struct solstice_entity* dst, struct solstice_entity* src) +{ + res_T res = RES_OK; + ASSERT(dst && src); + d3_set(dst->translation, src->translation); + d3_set(dst->rotation, src->rotation); + dst->type = src->type; + dst->data = src->data; + res = str_copy_and_clear(&dst->name, &src->name); + if(res != RES_OK) return res; + res = htable_str2sols_copy_and_clear(&dst->str2anchors, &src->str2anchors); + if(res != RES_OK) return res; + res = htable_str2sols_copy_and_clear(&dst->str2children, &src->str2children); + if(res != RES_OK) return res; + res = darray_anchor_id_copy_and_clear(&dst->anchors, &src->anchors); + if(res != RES_OK) return res; + res = darray_child_id_copy_and_clear(&dst->children, &src->children); + if(res != RES_OK) return res; + return RES_OK; +} + static INLINE size_t solstice_entity_get_anchors_count(const struct solstice_entity* entity) { diff --git a/src/parser/solstice_parser.c b/src/parser/solstice_parser.c @@ -2219,7 +2219,8 @@ parse_entity struct solstice_entity_id* out_isolent) { enum { ANCHORS, CHILDREN, DATA, NAME, TRANSFORM }; - struct solstice_entity* solent = NULL; + struct solstice_entity solent; + struct solstice_entity* psolent; const size_t *pisolent; size_t isolent = SIZE_MAX; intptr_t i, n; @@ -2228,6 +2229,8 @@ parse_entity res_T res = RES_OK; ASSERT(doc && entity && htable && out_isolent); + solstice_entity_init(parser->allocator, &solent); + pisolent = htable_yaml2sols_find(&parser->yaml2entities, &entity); if(pisolent) { isolent = *pisolent; @@ -2242,14 +2245,15 @@ parse_entity goto error; } - /* Allocate the entity */ + /* Allocate the entity but *DO NOT* retrieve a pointer onto it since the + * allocation of its children may update its memory location. Use the "on + * stack" entity `solent' instead. */ isolent = darray_entity_size_get(&parser->entities); res = darray_entity_resize(&parser->entities, isolent + 1); if(res != RES_OK) { log_err(parser, entity, "could not allocate the entity.\n"); goto error; } - solent = darray_entity_data_get(&parser->entities) + isolent; n = entity->data.mapping.pairs.top - entity->data.mapping.pairs.start; FOR_EACH(i, 0, n) { @@ -2276,26 +2280,26 @@ parse_entity if(!strcmp((char*)key->data.scalar.value, "anchors")) { SETUP_MASK(ANCHORS, "anchors"); res = parse_anchors - (parser, doc, val, &solent->str2anchors, &solent->anchors); + (parser, doc, val, &solent.str2anchors, &solent.anchors); } else if(!strcmp((char*)key->data.scalar.value, "children")) { SETUP_MASK(CHILDREN, "children"); res = parse_children - (parser, doc, val, &solent->str2children, &solent->children); + (parser, doc, val, &solent.str2children, &solent.children); } else if(!strcmp((char*)key->data.scalar.value, "geometry")) { SETUP_MASK(DATA, "data"); - solent->type = SOLSTICE_ENTITY_GEOMETRY; - res = parse_geometry(parser, doc, val, &solent->data.geometry); + solent.type = SOLSTICE_ENTITY_GEOMETRY; + res = parse_geometry(parser, doc, val, &solent.data.geometry); } else if(!strcmp((char*)key->data.scalar.value, "name")) { SETUP_MASK(NAME, "name"); - res = parse_identifier_string(parser, val, &solent->name); + res = parse_identifier_string(parser, val, &solent.name); } else if(!strcmp((char*)key->data.scalar.value, "pivot")) { SETUP_MASK(DATA, "data"); - solent->type = SOLSTICE_ENTITY_PIVOT; - res = parse_pivot(parser, doc, val, &solent->data.pivot); + solent.type = SOLSTICE_ENTITY_PIVOT; + res = parse_pivot(parser, doc, val, &solent.data.pivot); } else if(!strcmp((char*)key->data.scalar.value, "transform")) { SETUP_MASK(TRANSFORM, "transform"); res = parse_transform - (parser, doc, val, solent->translation, solent->rotation); + (parser, doc, val, solent.translation, solent.rotation); } else if(!strcmp((char*)key->data.scalar.value, "<<")) { /* Copy */ struct solstice_entity* cp_solent; pisolent = htable_yaml2sols_find(&parser->yaml2entities, &val); @@ -2305,7 +2309,7 @@ parse_entity goto error; } cp_solent = darray_entity_data_get(&parser->entities) + *pisolent; - res = solstice_entity_copy(solent, cp_solent); + res = solstice_entity_copy(&solent, cp_solent); if(res != RES_OK) { log_err(parser, val, "could not copy the entity.\n"); goto error; @@ -2333,6 +2337,13 @@ parse_entity #undef CHECK_PARAM } + psolent = darray_entity_data_get(&parser->entities) + isolent; + res = solstice_entity_copy_and_clear(psolent, &solent); + if(res != RES_OK) { + log_err(parser, entity, + "could not copy the loaded entity into the parser data structures.\n"); + goto error; + } res = entity_register_name(parser, entity, htable, isolent); if(res != RES_OK) goto error; @@ -2343,11 +2354,12 @@ parse_entity } exit: + solstice_entity_release(&solent); out_isolent->i = isolent; return res; error: - if(solent) { - htable_str2sols_erase(htable, &solent->name); + if(isolent != SIZE_MAX) { + htable_str2sols_erase(htable, &solent.name); darray_entity_pop_back(&parser->entities); isolent = SIZE_MAX; }