diff options
author | Lev Walkin <vlm@lionet.info> | 2017-08-06 23:23:04 -0700 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2017-08-06 23:23:04 -0700 |
commit | ea6635bdae9667bcf6111a25d896c556c946c11a (patch) | |
tree | 20c58aa4aca799baa682bf1c2ce271d06e5e3530 /libasn1fix | |
parent | e700b208bc0b252c85390a80ee63f3687fb2d970 (diff) |
better parsing information object class sets
Diffstat (limited to 'libasn1fix')
-rw-r--r-- | libasn1fix/asn1fix.c | 8 | ||||
-rw-r--r-- | libasn1fix/asn1fix_class.c | 2 | ||||
-rw-r--r-- | libasn1fix/asn1fix_class.h | 2 | ||||
-rw-r--r-- | libasn1fix/asn1fix_constraint.c | 2 | ||||
-rw-r--r-- | libasn1fix/asn1fix_cws.c | 286 | ||||
-rw-r--r-- | libasn1fix/asn1fix_export.c | 4 | ||||
-rw-r--r-- | libasn1fix/asn1fix_export.h | 6 | ||||
-rw-r--r-- | libasn1fix/asn1fix_misc.c | 9 | ||||
-rw-r--r-- | libasn1fix/asn1fix_retrieve.c | 6 | ||||
-rw-r--r-- | libasn1fix/asn1fix_retrieve.h | 4 |
10 files changed, 245 insertions, 84 deletions
diff --git a/libasn1fix/asn1fix.c b/libasn1fix/asn1fix.c index 124576f2..2cdf5271 100644 --- a/libasn1fix/asn1fix.c +++ b/libasn1fix/asn1fix.c @@ -339,15 +339,15 @@ phase_1_1(arg_t *arg, int prm2) { RET2RVAL(ret, rvalue); /* - * Parse class objects and fill up the object class with data. + * Resolve references in constraints. */ - ret = asn1f_parse_class_object(arg); + ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints); RET2RVAL(ret, rvalue); /* - * Resolve references in constraints. + * Parse class information object sets. */ - ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints); + ret = asn1f_parse_class_object(arg); RET2RVAL(ret, rvalue); /* diff --git a/libasn1fix/asn1fix_class.c b/libasn1fix/asn1fix_class.c index 32ad8963..02bcaaca 100644 --- a/libasn1fix/asn1fix_class.c +++ b/libasn1fix/asn1fix_class.c @@ -1,7 +1,7 @@ #include "asn1fix_internal.h" asn1p_expr_t * -asn1f_class_access(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref) { +asn1f_class_access(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *ref) { asn1p_expr_t *ioclass; asn1p_expr_t *classfield; asn1p_expr_t *expr; diff --git a/libasn1fix/asn1fix_class.h b/libasn1fix/asn1fix_class.h index 2120bc8c..b0c143bd 100644 --- a/libasn1fix/asn1fix_class.h +++ b/libasn1fix/asn1fix_class.h @@ -4,6 +4,6 @@ /* * Fetch the element from the class-related stuff (thing) by its reference. */ -asn1p_expr_t *asn1f_class_access(arg_t *, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *); +asn1p_expr_t *asn1f_class_access(arg_t *, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *); #endif /* ASN1FIX_CLASS_H */ diff --git a/libasn1fix/asn1fix_constraint.c b/libasn1fix/asn1fix_constraint.c index 97fa589b..ec13bd6b 100644 --- a/libasn1fix/asn1fix_constraint.c +++ b/libasn1fix/asn1fix_constraint.c @@ -356,7 +356,7 @@ constraint_object_resolve(arg_t *arg, asn1p_value_t *value) { asn1p_expr_t tmp_expr = *arg->expr; asn1p_expr_t *saved_expr = arg->expr; - tmp_expr.meta_type = AMT_VALUE; + tmp_expr.meta_type = AMT_VALUESET; tmp_expr.expr_type = A1TC_REFERENCE; tmp_expr.value = value; arg->expr = &tmp_expr; diff --git a/libasn1fix/asn1fix_cws.c b/libasn1fix/asn1fix_cws.c index e0ab9419..de2d2406 100644 --- a/libasn1fix/asn1fix_cws.c +++ b/libasn1fix/asn1fix_cws.c @@ -3,10 +3,10 @@ static int _asn1f_parse_class_object_data(arg_t *, asn1p_expr_t *eclass, struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax, - uint8_t *buf, const uint8_t *bend, - int optional_mode, uint8_t **newpos); -static int _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell, uint8_t *buf, const uint8_t *bend); -static asn1p_wsyntx_chunk_t *asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, uint8_t *buf); + const uint8_t *buf, const uint8_t *bend, + int optional_mode, const uint8_t **newpos); +static int _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell, const uint8_t *buf, const uint8_t *bend); +static asn1p_wsyntx_chunk_t *asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, const uint8_t *buf); int asn1f_check_class_object(arg_t *arg) { @@ -15,11 +15,12 @@ asn1f_check_class_object(arg_t *arg) { asn1p_ioc_row_t *row; int ret; - if(expr->meta_type != AMT_VALUE + if(expr->meta_type != AMT_VALUESET || expr->expr_type != A1TC_REFERENCE || !expr->value - || expr->value->type != ATV_UNPARSED) + || expr->value->type != ATV_UNPARSED) { return 0; + } eclass = asn1f_find_terminal_type(arg, expr); if(!eclass @@ -49,19 +50,193 @@ asn1f_check_class_object(arg_t *arg) { return ret; } +static int +_asn1f_is_ioc_row_duplicate(asn1p_ioc_row_t **rows, size_t count, asn1p_ioc_row_t *row) { + for(size_t i = 0; i < count; i++) { + switch(asn1p_ioc_row_match(rows[i], row)) { + default: + case -1: + return -1; + case 1: + continue; + case 0: + return 1; /* Duplicate! */ + } + } + return 0; +} + +struct parse_object_key { + arg_t *arg; + asn1p_expr_t *expr; /* InformationObjectSet */ + asn1p_expr_t *eclass; /* CLASS */ +}; + +static int +_asn1f_add_row(arg_t *arg, asn1p_expr_t *expr, asn1p_ioc_row_t *row) { + void *new_rows_ptr; + + switch(_asn1f_is_ioc_row_duplicate(expr->object_class_matrix.row, + expr->object_class_matrix.rows, row)) { + case -1: + DEBUG("Found Information Object Duplicate in %s", expr->Identifier, + expr->_lineno); + return -1; + case 0: + /* Not a duplicate */ + break; + case 1: + /* Proper duplicate detected; ignore */ + asn1p_ioc_row_delete(row); + return 0; + } + + new_rows_ptr = realloc(expr->object_class_matrix.row, + (expr->object_class_matrix.rows + 1) + * sizeof(expr->object_class_matrix.row[0])); + assert(new_rows_ptr); + expr->object_class_matrix.row = new_rows_ptr; + expr->object_class_matrix.row[expr->object_class_matrix.rows] = row; + expr->object_class_matrix.rows++; + /* Propagate max identifier length */ + if(expr->object_class_matrix.max_identifier_length + < row->max_identifier_length) + expr->object_class_matrix.max_identifier_length + = row->max_identifier_length; + + return 0; +} + +/* + * Given a single blob of unparsed Information Object specification, parse it + * into a given InformationObjectSet. + */ +static int +_asn1f_parse_object_cb(const uint8_t *buf, size_t size, void *keyp) { + struct parse_object_key *key = keyp; + arg_t *arg = key->arg; + asn1p_expr_t *expr = key->expr; + asn1p_expr_t *eclass = key->eclass; + asn1p_ioc_row_t *row; + int ret; + + row = asn1p_ioc_row_new(eclass); + assert(row); + + ret = _asn1f_parse_class_object_data(arg, eclass, row, eclass->with_syntax, + buf, buf + size, 0, 0); + if(ret) { + LOG((int)(ret < 0), + "Cannot parse %s of CLASS %s found at line %d", + expr->Identifier, eclass->Identifier, expr->_lineno); + asn1p_ioc_row_delete(row); + return ret; + } + + /* Add object to a CLASS. */ + if(_asn1f_add_row(arg, eclass, row) != 0) + return -1; + + /* + * Add a copy of the object to the Information Object Set. + */ + row = asn1p_ioc_row_new(eclass); + assert(row); + ret = _asn1f_parse_class_object_data(arg, eclass, row, eclass->with_syntax, + buf, buf + size, 0, 0); + assert(ret == 0); + + if(_asn1f_add_row(arg, expr, row) != 0) + return -1; + + return 0; +} + +static int +_asn1f_foreach_unparsed_union(const asn1p_constraint_t *ct_union, + int (*process)(const uint8_t *buf, size_t size, + void *key), + void *key) { + assert(ct_union->type == ACT_CA_UNI); + + for(size_t j = 0; j < ct_union->el_count; j++) { + const asn1p_constraint_t *ct2 = ct_union->elements[j]; + if(ct2->type == ACT_EL_VALUE && ct2->value->type == ATV_UNPARSED) { + if(process + && process(ct2->value->value.string.buf + 1, + ct2->value->value.string.size - 2, key) + != 0) { + return -1; + } + continue; + } + return -1; + } + + return 0; +} + +static int +_asn1f_foreach_unparsed(const asn1p_constraint_t *ct, + int (*process)(const uint8_t *buf, size_t size, + void *key), + void *key) { + if(!ct) return -1; + if(ct->type == ACT_CA_UNI) { + return _asn1f_foreach_unparsed_union(ct, process, key); + } + if(ct->type != ACT_CA_CSV) return -1; + + for(size_t i = 0; i < ct->el_count; i++) { + const asn1p_constraint_t *ct1 = ct->elements[i]; + switch(ct1->type) { + case ACT_EL_EXT: + break; + case ACT_CA_UNI: + if(_asn1f_foreach_unparsed_union(ct1, process, key) != 0) { + return -1; + } + break; + default: + return -1; + } + } + + return 0; +} + +static int +_asn1f_constraint_looks_like_object_set(const asn1p_constraint_t *ct) { + return 0 == _asn1f_foreach_unparsed(ct, NULL, NULL); +} + int asn1f_parse_class_object(arg_t *arg) { asn1p_expr_t *expr = arg->expr; asn1p_expr_t *eclass; - asn1p_ioc_row_t *row; - void *new_rows_ptr; - int ret; - - if(expr->meta_type != AMT_VALUE - || expr->expr_type != A1TC_REFERENCE - || !expr->value - || expr->value->type != ATV_UNPARSED) - return 0; + enum { + FROM_VALUE, + FROM_CONSTRAINT, + } source = FROM_VALUE; + + if(expr->meta_type == AMT_VALUE + && expr->expr_type == A1TC_REFERENCE + && expr->value && expr->value->type == ATV_UNPARSED) { + source = FROM_VALUE; + } else if(expr->meta_type != AMT_VALUESET + || expr->expr_type != A1TC_REFERENCE) { + return 0; + } else if(expr->value && expr->value->type == ATV_UNPARSED) { + source = FROM_VALUE; + } else if(!expr->value) { + if(_asn1f_constraint_looks_like_object_set(expr->constraints)) { + source = FROM_CONSTRAINT; + } else { + return 0; + } + } else { + return 0; + } /* * Find the governing class. @@ -82,35 +257,27 @@ asn1f_parse_class_object(arg_t *arg) { return 0; } - row = asn1p_ioc_row_new(eclass); - assert(row); - - ret = _asn1f_parse_class_object_data(arg, eclass, row, - eclass->with_syntax, - expr->value->value.string.buf + 1, - expr->value->value.string.buf - + expr->value->value.string.size - 1, - 0, 0); - if(ret) { - LOG((int)(ret < 0), - "Cannot parse %s of CLASS %s found at line %d", - expr->Identifier, eclass->Identifier, expr->_lineno); - asn1p_ioc_row_delete(row); - return ret; - } - - new_rows_ptr = realloc(eclass->object_class_matrix.row, - (eclass->object_class_matrix.rows + 1) - * sizeof(eclass->object_class_matrix.row[0])); - assert(new_rows_ptr); - eclass->object_class_matrix.row = new_rows_ptr; - eclass->object_class_matrix.row[eclass->object_class_matrix.rows] = row; - eclass->object_class_matrix.rows++; - /* Propagate max identifier length */ - if(eclass->object_class_matrix.max_identifier_length - < row->max_identifier_length) - eclass->object_class_matrix.max_identifier_length - = row->max_identifier_length; + struct parse_object_key key = { + .arg = arg, + .expr = expr, + .eclass = eclass, + }; + + switch(source) { + case FROM_VALUE: + if(_asn1f_parse_object_cb(expr->value->value.string.buf + 1, + expr->value->value.string.size - 2, &key) + != 0) { + return -1; + } + break; + case FROM_CONSTRAINT: + if(_asn1f_foreach_unparsed(expr->constraints, _asn1f_parse_object_cb, + &key) + != 0) { + return -1; + } + } return 0; } @@ -120,8 +287,8 @@ asn1f_parse_class_object(arg_t *arg) { static int _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass, struct asn1p_ioc_row_s *row, asn1p_wsyntx_t *syntax, - uint8_t *buf, const uint8_t *bend, - int optional_mode, uint8_t **newpos) { + const uint8_t *buf, const uint8_t *bend, + int optional_mode, const uint8_t **newpos) { struct asn1p_wsyntx_chunk_s *chunk; int ret; @@ -145,8 +312,8 @@ _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass, case WC_FIELD: { struct asn1p_ioc_cell_s *cell; asn1p_wsyntx_chunk_t *next_literal; - uint8_t *buf_old = buf; - uint8_t *p = 0; + const uint8_t *buf_old = buf; + const uint8_t *p = 0; SKIPSPACES; @@ -154,7 +321,7 @@ _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass, if(!next_literal) { p += (bend - p); } else { - p = (uint8_t *)strstr((char *)buf, (char *)next_literal->content.token); + p = (uint8_t *)strstr((const char *)buf, (const char *)next_literal->content.token); if(!p) { if (!optional_mode) FATAL("Next literal \"%s\" not found !", next_literal->content.token); @@ -181,7 +348,7 @@ _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass, if(newpos) *newpos = buf; } break; case WC_OPTIONALGROUP: { - uint8_t *np = 0; + const uint8_t *np = 0; SKIPSPACES; ret = _asn1f_parse_class_object_data(arg, eclass, row, chunk->content.syntax, buf, bend, 1, &np); @@ -200,9 +367,10 @@ _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass, static int -_asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_ioc_cell_s *cell, - uint8_t *buf, const uint8_t *bend) { - asn1p_expr_t *expr = (asn1p_expr_t *)NULL; +_asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, + struct asn1p_ioc_cell_s *cell, const uint8_t *buf, + const uint8_t *bend) { + asn1p_expr_t *expr = (asn1p_expr_t *)NULL; int idLength; char *p; int new_ref = 1; @@ -259,7 +427,7 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_i free(pp); return -1; } - DEBUG("ASN.1 :\n\n%s\n", pp); + DEBUG("ASN.1:\n\n%s\n", pp); assert(ret < psize); psize = ret; @@ -281,11 +449,9 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_i assert(expr); free(expr->Identifier); - expr->module = arg->expr->module; - expr->_lineno = arg->expr->_lineno; + expr->parent_expr = NULL; + asn1p_expr_set_source(expr, arg->expr->module, arg->expr->_lineno); if (expr->reference) { - expr->reference->module = arg->expr->module; - expr->reference->_lineno = arg->expr->_lineno; expr->Identifier = strdup(expr->reference->components[expr->reference->comp_count - 1].name); } else { expr->Identifier = p; @@ -327,7 +493,7 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_i } static asn1p_wsyntx_chunk_t * -asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, uint8_t *buf) +asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, const uint8_t *buf) { asn1p_wsyntx_chunk_t *next_chunk; @@ -338,7 +504,7 @@ asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, ui break; next_chunk = TQ_NEXT(syntax->parent, next); } else if(next_chunk->type == WC_LITERAL) { - if(strstr((char *)buf, (char *)next_chunk->content.token)) + if(strstr((const char *)buf, (char *)next_chunk->content.token)) break; if(!syntax->parent) break; diff --git a/libasn1fix/asn1fix_export.c b/libasn1fix/asn1fix_export.c index bb598bf4..b5709258 100644 --- a/libasn1fix/asn1fix_export.c +++ b/libasn1fix/asn1fix_export.c @@ -8,7 +8,7 @@ asn1p_expr_t * asn1f_lookup_symbol_ex( asn1p_t *asn, asn1p_expr_t *expr, - asn1p_ref_t *ref) { + const asn1p_ref_t *ref) { arg_t arg; memset(&arg, 0, sizeof(arg)); @@ -28,7 +28,7 @@ asn1f_class_access_ex(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, asn1p_expr_t *rhs_pspecs, - asn1p_ref_t *ref) { + const asn1p_ref_t *ref) { arg_t arg; memset(&arg, 0, sizeof(arg)); diff --git a/libasn1fix/asn1fix_export.h b/libasn1fix/asn1fix_export.h index 0411843b..f03807ee 100644 --- a/libasn1fix/asn1fix_export.h +++ b/libasn1fix/asn1fix_export.h @@ -10,7 +10,7 @@ /* * Create a human-readable representation of a reference and value. */ -char const *asn1f_printable_reference(asn1p_ref_t *ref); +char const *asn1f_printable_reference(const asn1p_ref_t *ref); char const *asn1f_printable_value(asn1p_value_t *value); /* @@ -19,13 +19,13 @@ char const *asn1f_printable_value(asn1p_value_t *value); asn1p_expr_t *asn1f_lookup_symbol_ex( asn1p_t *asn, asn1p_expr_t *expr, - asn1p_ref_t *ref); + const asn1p_ref_t *ref); /* * Exportable version of an asn1f_class_access(). */ asn1p_expr_t *asn1f_class_access_ex(asn1p_t *asn, asn1p_module_t *mod, - asn1p_expr_t *expr, asn1p_expr_t *rhs_rspecs, asn1p_ref_t *); + asn1p_expr_t *expr, asn1p_expr_t *rhs_rspecs, const asn1p_ref_t *); /* * Exportable version of asn1f_find_terminal_type(). diff --git a/libasn1fix/asn1fix_misc.c b/libasn1fix/asn1fix_misc.c index e5f4f797..23ae24fc 100644 --- a/libasn1fix/asn1fix_misc.c +++ b/libasn1fix/asn1fix_misc.c @@ -2,14 +2,9 @@ #include "asn1fix.h" char const * -asn1f_printable_reference(asn1p_ref_t *ref) { +asn1f_printable_reference(const asn1p_ref_t *ref) { if(ref) { - asn1p_value_t v; - - v.type = ATV_REFERENCED; - v.value.reference = ref; - - return asn1f_printable_value(&v); + return asn1p_ref_string(ref); } else { return "<no ref>"; } diff --git a/libasn1fix/asn1fix_retrieve.c b/libasn1fix/asn1fix_retrieve.c index 1700914f..f086ed39 100644 --- a/libasn1fix/asn1fix_retrieve.c +++ b/libasn1fix/asn1fix_retrieve.c @@ -80,7 +80,7 @@ asn1f_lookup_in_imports(arg_t *arg, asn1p_module_t *mod, const char *name) { } asn1p_module_t * -asn1f_lookup_module(arg_t *arg, const char *module_name, asn1p_oid_t *oid) { +asn1f_lookup_module(arg_t *arg, const char *module_name, const asn1p_oid_t *oid) { asn1p_module_t *mod; assert(module_name); @@ -147,7 +147,7 @@ asn1f_lookup_module(arg_t *arg, const char *module_name, asn1p_oid_t *oid) { } static asn1p_expr_t * -asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref, int recursion_depth) { +asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *ref, int recursion_depth) { asn1p_expr_t *ref_tc; /* Referenced tc */ asn1p_module_t *imports_from; char *modulename; @@ -369,7 +369,7 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspe asn1p_expr_t * asn1f_lookup_symbol(arg_t *arg, - asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, asn1p_ref_t *ref) { + asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, const asn1p_ref_t *ref) { return asn1f_lookup_symbol_impl(arg, mod, rhs_pspecs, ref, 0); } diff --git a/libasn1fix/asn1fix_retrieve.h b/libasn1fix/asn1fix_retrieve.h index 2d529ef9..95b8330f 100644 --- a/libasn1fix/asn1fix_retrieve.h +++ b/libasn1fix/asn1fix_retrieve.h @@ -31,7 +31,7 @@ asn1p_module_t *asn1f_lookup_in_imports(arg_t *arg, asn1p_module_t *mod, const c */ asn1p_module_t *asn1f_lookup_module(arg_t *arg, const char *module_name, - asn1p_oid_t *module_oid); + const asn1p_oid_t *module_oid); /* * Return the reference to a destination of the given reference, @@ -40,7 +40,7 @@ asn1p_module_t *asn1f_lookup_module(arg_t *arg, asn1p_expr_t *asn1f_lookup_symbol(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspecs, - asn1p_ref_t *ref); + const asn1p_ref_t *ref); /* * Recursively find the original type for the given expression. |