diff --git a/libasn1fix/asn1fix.c b/libasn1fix/asn1fix.c index 6549a2a61ff84d86d2bc3553062dccbb4071192b..63cd148d985ba2055987c9e6491bdd548b92c65b 100644 --- a/libasn1fix/asn1fix.c +++ b/libasn1fix/asn1fix.c @@ -381,8 +381,7 @@ asn1f_resolve_constraints(arg_t *arg) { DEBUG("(%s)", arg->expr->Identifier); - ret = asn1constraint_resolve(arg, arg->expr->module, - arg->expr->constraints, etype, 0); + ret = asn1constraint_resolve(arg, arg->expr->constraints, etype, 0); RET2RVAL(ret, rvalue); return rvalue; diff --git a/libasn1fix/asn1fix_constraint.c b/libasn1fix/asn1fix_constraint.c index 808f4e8a3e3e40c327599aac8105c0368a023ee0..0faee51d5764a83a16d7f54a12841d7a5891eb2c 100644 --- a/libasn1fix/asn1fix_constraint.c +++ b/libasn1fix/asn1fix_constraint.c @@ -2,12 +2,14 @@ #include "asn1fix_constraint.h" #include "asn1fix_crange.h" -static void _remove_exceptions(arg_t *arg, asn1p_constraint_t *ct); -static int constraint_value_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype); +static void _remove_extensions(arg_t *arg, asn1p_constraint_t *ct); +static int constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct); +static int constraint_value_resolve(arg_t *arg, asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype); int asn1constraint_pullup(arg_t *arg) { asn1p_expr_t *expr = arg->expr; + asn1p_expr_t *top_parent; asn1p_constraint_t *ct_parent; asn1p_constraint_t *ct_expr; int ret; @@ -63,6 +65,17 @@ asn1constraint_pullup(arg_t *arg) { if(!ct_parent && !ct_expr) return 0; /* No constraints to consider */ + /* + * Resolve constraints, if not already resolved. + */ + top_parent = asn1f_find_terminal_type(arg, arg->expr); + ret = asn1constraint_resolve(arg, ct_expr, + top_parent ? top_parent->expr_type : A1TC_INVALID, 0); + if(ret) return ret; + + /* + * Copy parent type constraints. + */ if(ct_parent) { ct_parent = asn1p_constraint_clone(ct_parent); assert(ct_parent); @@ -89,7 +102,7 @@ asn1constraint_pullup(arg_t *arg) { /* * If we have a parent, remove all the extensions (46.4). */ - _remove_exceptions(arg, ct_parent); + _remove_extensions(arg, ct_parent); expr->combined_constraints = ct_parent; if(ct_expr->type == ACT_CA_SET) { @@ -119,7 +132,7 @@ asn1constraint_pullup(arg_t *arg) { } int -asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct, asn1p_expr_type_e etype, enum asn1p_constraint_type_e effective_type) { +asn1constraint_resolve(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_type_e etype, enum asn1p_constraint_type_e effective_type) { enum asn1p_constraint_type_e real_constraint_type; unsigned int el; int rvalue = 0; @@ -183,18 +196,23 @@ asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct, /* * Resolve all possible references, wherever they occur. */ + if(ct->containedSubtype) { + assert(ct->containedSubtype->type == ATV_REFERENCED); + ret = constraint_type_resolve(arg, ct); + RET2RVAL(ret, rvalue); + } if(ct->value && ct->value->type == ATV_REFERENCED) { - ret = constraint_value_resolve(arg, mod, + ret = constraint_value_resolve(arg, &ct->value, real_constraint_type); RET2RVAL(ret, rvalue); } if(ct->range_start && ct->range_start->type == ATV_REFERENCED) { - ret = constraint_value_resolve(arg, mod, + ret = constraint_value_resolve(arg, &ct->range_start, real_constraint_type); RET2RVAL(ret, rvalue); } if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) { - ret = constraint_value_resolve(arg, mod, + ret = constraint_value_resolve(arg, &ct->range_stop, real_constraint_type); RET2RVAL(ret, rvalue); } @@ -203,7 +221,7 @@ asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct, * Proceed recursively. */ for(el = 0; el < ct->el_count; el++) { - ret = asn1constraint_resolve(arg, mod, ct->elements[el], + ret = asn1constraint_resolve(arg, ct->elements[el], etype, effective_type); RET2RVAL(ret, rvalue); } @@ -212,13 +230,13 @@ asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct, } static void -_remove_exceptions(arg_t *arg, asn1p_constraint_t *ct) { +_remove_extensions(arg_t *arg, asn1p_constraint_t *ct) { unsigned int i; for(i = 0; i < ct->el_count; i++) { if(ct->elements[i]->type == ACT_EL_EXT) break; - _remove_exceptions(arg, ct->elements[i]); + _remove_extensions(arg, ct->elements[i]); } /* Remove the elements at and after the extensibility mark */ @@ -232,17 +250,72 @@ _remove_exceptions(arg_t *arg, asn1p_constraint_t *ct) { ct->elements[i] = 0; } +static int +constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct) { + asn1p_expr_t *rtype; + arg_t tmparg; + int ret; + + DEBUG("(\"%s\")", asn1f_printable_value(ct->containedSubtype)); + + assert(ct->containedSubtype->type == ATV_REFERENCED); + + rtype = asn1f_lookup_symbol(arg, arg->expr->module, + ct->containedSubtype->value.reference); + if(!rtype) { + FATAL("Cannot find type \"%s\" in constraints at line %d", + asn1f_printable_value(ct->containedSubtype), + ct->_lineno); + return -1; + } + + + tmparg = *arg; + tmparg.expr = rtype; + tmparg.mod = rtype->module; + ret = asn1constraint_pullup(&tmparg); + if(ret) return ret; + + if(rtype->combined_constraints) { + asn1p_constraint_t *ct_expr; + ct_expr = asn1p_constraint_clone(rtype->combined_constraints); + assert(ct_expr); + + _remove_extensions(arg, ct_expr); + + if(ct_expr->type == ACT_CA_SET) { + unsigned int i; + for(i = 0; i < ct_expr->el_count; i++) { + if(asn1p_constraint_insert( + ct, ct_expr->elements[i])) { + asn1p_constraint_free(ct_expr); + return -1; + } else { + ct_expr->elements[i] = 0; + } + } + asn1p_constraint_free(ct_expr); + } else { + ret = asn1p_constraint_insert(ct, ct_expr); + assert(ret == 0); + } + + ct->type = ACT_CA_SET; + asn1p_value_free(ct->containedSubtype); + ct->containedSubtype = NULL; + } + + return 0; +} static int -constraint_value_resolve(arg_t *arg, asn1p_module_t *mod, +constraint_value_resolve(arg_t *arg, asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype) { asn1p_expr_t static_expr; arg_t tmp_arg; int rvalue = 0; int ret; - (void)mod; - DEBUG("(\"%s\", within <%s>)", asn1f_printable_value(*value), asn1p_constraint_type2str(real_ctype)); @@ -260,3 +333,4 @@ constraint_value_resolve(arg_t *arg, asn1p_module_t *mod, return rvalue; } + diff --git a/libasn1fix/asn1fix_constraint.h b/libasn1fix/asn1fix_constraint.h index cc6621f998ce23484378a81773d2f99be316b19c..9e692efab5f35be7b89bbec5ce3433658a4b2260 100644 --- a/libasn1fix/asn1fix_constraint.h +++ b/libasn1fix/asn1fix_constraint.h @@ -4,8 +4,7 @@ /* * Resolve referenced values inside constraints. */ -int asn1constraint_resolve(arg_t *arg, asn1p_module_t *module, - asn1p_constraint_t *ct, +int asn1constraint_resolve(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_type_e topmost_parent_expression_type, enum asn1p_constraint_type_e effective_constraint_type); diff --git a/libasn1fix/asn1fix_constraint_compat.c b/libasn1fix/asn1fix_constraint_compat.c index 5eb93f0ba86c8f82074e41475b5ab8b67fb520c0..17f398606acdc744dfd148d84e629e735dd4256a 100644 --- a/libasn1fix/asn1fix_constraint_compat.c +++ b/libasn1fix/asn1fix_constraint_compat.c @@ -16,6 +16,8 @@ asn1constraint_compatible(asn1p_expr_type_e expr_type, switch(constr_type) { case ACT_INVALID: return 0; + case ACT_EL_TYPE: + return 1; case ACT_EL_VALUE: return 1; case ACT_EL_RANGE: