aboutsummaryrefslogtreecommitdiffstats
path: root/libasn1fix
diff options
context:
space:
mode:
authorBi-Ruei, Chiu <biruei.chiu@gmail.com>2017-05-07 21:00:51 +0800
committerBi-Ruei, Chiu <biruei.chiu@gmail.com>2017-05-07 22:20:30 +0800
commit80fd3065f4868c5a9c6afe493391a45558ed8463 (patch)
tree9fc270cb66040f96a172437010156e88c3f566c7 /libasn1fix
parent4021e4ba623b2885a8c859379bc858644c2e1d34 (diff)
Merge PR99 and its fixes to support parsing Information Object and Information Object Set
This is a collection of works : 1. Based on @zhanglei002's pull request 99. 2. A fix by @AuthenticEshkinKot and merged by @mouse07410 at commit 2c8d366bbe1fc4e4c041e9b0eb9779f8a42d754b of https://github.com/mouse07410/asn1c to support parsing of Information Object and Information Object Set 3. A fix by @Uri Blumenthal in asn1fix_derefv.c at : commit ec0ade4f87c807e763e3f35fc5466adb6dda3473 of https://github.com/mouse07410/asn1c to solve crash on asn1p_value_free(). 4. My pull request 18 to @mouse07410's https://github.com/mouse07410/asn1c to solve problems found during parsing ASN.1 modules of S1AP, RANAP and J2735-201603. 5. My pull request 22 to @mouse07410's https://github.com/mouse07410/asn1c to solve issue 147 and to solve the problem during parsing ASN.1 module of NBAP. 6. My pull request 23 to @mouse07410's https://github.com/mouse07410/asn1c to fix memory leakage introduced in aforementioned commits. Most code changes are the same as pull request 153 to this repository. 7. A fix of my bug in item 6 which result asn1c crash, fixed by @mouse07410.
Diffstat (limited to 'libasn1fix')
-rw-r--r--libasn1fix/asn1fix.c11
-rw-r--r--libasn1fix/asn1fix_constraint.c26
-rw-r--r--libasn1fix/asn1fix_cws.c216
-rw-r--r--libasn1fix/asn1fix_cws.h1
-rw-r--r--libasn1fix/asn1fix_derefv.c1
-rw-r--r--libasn1fix/asn1fix_param.c22
-rw-r--r--libasn1fix/asn1fix_retrieve.c66
-rw-r--r--libasn1fix/asn1fix_value.c24
8 files changed, 289 insertions, 78 deletions
diff --git a/libasn1fix/asn1fix.c b/libasn1fix/asn1fix.c
index 8d2317f4..e6af2f24 100644
--- a/libasn1fix/asn1fix.c
+++ b/libasn1fix/asn1fix.c
@@ -247,6 +247,7 @@ asn1f_fix_module__phase_2(arg_t *arg) {
int ret;
TQ_FOR(expr, &(arg->mod->members), next) {
+
arg->expr = expr;
/*
@@ -499,6 +500,16 @@ asn1f_check_duplicate(arg_t *arg) {
arg->expr->Identifier))
continue;
+ /* resolve clash of Identifier in different modules */
+ int oid_exist = (tmparg.expr->module->module_oid && arg->expr->module->module_oid);
+ if ((!oid_exist && strcmp(tmparg.expr->module->ModuleName, arg->expr->module->ModuleName)) ||
+ (oid_exist && !asn1p_oid_compare(tmparg.expr->module->module_oid, arg->expr->module->module_oid))) {
+
+ tmparg.expr->_mark |= TM_NAMECLASH;
+ arg->expr->_mark |= TM_NAMECLASH;
+ continue;
+ }
+
diff_files = strcmp(arg->mod->source_file_name,
tmparg.mod->source_file_name) ? 1 : 0;
diff --git a/libasn1fix/asn1fix_constraint.c b/libasn1fix/asn1fix_constraint.c
index 847bdcea..97fa589b 100644
--- a/libasn1fix/asn1fix_constraint.c
+++ b/libasn1fix/asn1fix_constraint.c
@@ -4,6 +4,7 @@
static void _remove_extensions(arg_t *arg, asn1p_constraint_t *ct, int flast);
static int constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct);
+static int constraint_object_resolve(arg_t *arg, asn1p_value_t *value);
static int constraint_value_resolve(arg_t *arg, asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype);
int
@@ -214,6 +215,10 @@ asn1constraint_resolve(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_type_e ety
&ct->range_stop, real_constraint_type);
RET2RVAL(ret, rvalue);
}
+ if (ct->value && ct->value->type == ATV_UNPARSED && etype == A1TC_CLASSDEF) {
+ ret = constraint_object_resolve(arg, ct->value);
+ RET2RVAL(ret, rvalue);
+ }
/*
* Proceed recursively.
@@ -346,3 +351,24 @@ constraint_value_resolve(arg_t *arg,
return rvalue;
}
+static int
+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.expr_type = A1TC_REFERENCE;
+ tmp_expr.value = value;
+ arg->expr = &tmp_expr;
+
+ if (asn1f_check_class_object(arg)) {
+ arg->expr = saved_expr;
+ FATAL("Parsing ObjectSet %s failed at %d", arg->expr->Identifier,
+ arg->expr->_lineno);
+ return -1;
+ }
+
+ arg->expr = saved_expr;
+ return 0;
+}
+
diff --git a/libasn1fix/asn1fix_cws.c b/libasn1fix/asn1fix_cws.c
index 312a65b0..245b1c1b 100644
--- a/libasn1fix/asn1fix_cws.c
+++ b/libasn1fix/asn1fix_cws.c
@@ -6,6 +6,48 @@ static int _asn1f_parse_class_object_data(arg_t *, asn1p_expr_t *eclass,
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);
+
+int
+asn1f_check_class_object(arg_t *arg) {
+ asn1p_expr_t *expr = arg->expr;
+ asn1p_expr_t *eclass;
+ asn1p_ioc_row_t *row;
+ int ret;
+
+ if(expr->meta_type != AMT_VALUE
+ || expr->expr_type != A1TC_REFERENCE
+ || !expr->value
+ || expr->value->type != ATV_UNPARSED)
+ return 0;
+
+ eclass = asn1f_find_terminal_type(arg, expr);
+ if(!eclass
+ || eclass->meta_type != AMT_OBJECTCLASS
+ || eclass->expr_type != A1TC_CLASSDEF) {
+ return 0;
+ }
+
+ if(!eclass->with_syntax) {
+ DEBUG("Can't process classes without %s just yet",
+ "WITH SYNTAX");
+ 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);
+
+ asn1p_ioc_row_delete(row);
+
+ return ret;
+}
int
asn1f_parse_class_object(arg_t *arg) {
@@ -102,32 +144,25 @@ _asn1f_parse_class_object_data(arg_t *arg, asn1p_expr_t *eclass,
case WC_WHITESPACE: break; /* Ignore whitespace */
case WC_FIELD: {
struct asn1p_ioc_cell_s *cell;
- int lbraces = 0;
- uint8_t *p;
+ asn1p_wsyntx_chunk_t *next_literal;
+ uint8_t *buf_old = buf;
+ uint8_t *p = 0;
SKIPSPACES;
- p = buf;
- if(p < bend && *p == '{')
- lbraces = 1, p++;
- for(; p < bend; p++) {
- if(lbraces) {
- /* Search the terminating brace */
- switch(*p) {
- case '}': lbraces--; break;
- case '{': lbraces++; break;
- }
- } else if(isspace(*p)) {
- break;
+ next_literal = asn1f_next_literal_chunk(syntax, chunk, buf);
+ if(!next_literal) {
+ p += (bend - p);
+ } else {
+ p = (uint8_t *)strstr((char *)buf, (char *)next_literal->content.token);
+ if(!p) {
+ if (!optional_mode)
+ FATAL("Next literal \"%s\" not found !", next_literal->content.token);
+
+ if(newpos) *newpos = buf_old;
+ return -1;
}
}
- if(lbraces) {
- FATAL("Field reference %s found in class value definition for %s at line %d can not be satisfied by broken value \"%s\"",
- chunk->content.token,
- arg->expr->Identifier, arg->expr->_lineno, buf);
- if(newpos) *newpos = buf;
- return -1;
- }
cell = asn1p_ioc_row_cell_fetch(row,
chunk->content.token);
if(cell == NULL) {
@@ -167,10 +202,15 @@ _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_ref_t *ref;
+ asn1p_expr_t *expr = (asn1p_expr_t *)NULL;
int idLength;
char *p;
+ int new_ref = 1;
+ asn1p_t *asn;
+ asn1p_module_t *mod;
+ asn1p_expr_t *type_expr = (asn1p_expr_t *)NULL;
+ int i, ret = 0, psize;
+ char *pp;
if((bend - buf) <= 0) {
FATAL("Assignment warning: empty string is being assigned into %s for %s at line %d",
@@ -183,37 +223,89 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_i
assert(p);
memcpy(p, buf, bend - buf);
p[bend - buf] = '\0';
+ /* remove trailing space */
+ for (i = bend - buf - 1; (i > 0) && isspace(p[i]); i--)
+ p[i] = '\0';
- if(!isalpha(*p)) {
+ /* This value 100 should be larger than following formatting string */
+ psize = bend - buf + 100;
+ pp = malloc(psize);
+ if(pp == NULL) {
+ free(p);
+ return -1;
+ }
- if(isdigit(*p)) {
- asn1c_integer_t value;
- if(asn1p_atoi(p, &value)) {
- FATAL("Value %s at line %d is too large for this compiler! Contact the asn1c author.\n", p, arg->expr->_lineno);
- return -1;
- }
- expr = asn1p_expr_new(arg->expr->_lineno, arg->expr->module);
- expr->Identifier = p;
- expr->meta_type = AMT_VALUE;
- expr->expr_type = ASN_BASIC_INTEGER;
- expr->value = asn1p_value_fromint(value);
+ if(cell->field->expr_type == A1TC_CLASSFIELD_TFS) {
+ ret = snprintf(pp, psize,
+ "M DEFINITIONS ::=\nBEGIN\n"
+ "V ::= %s\n"
+ "END\n",
+ p
+ );
+ } else if(cell->field->expr_type == A1TC_CLASSFIELD_FTVFS) {
+ type_expr = TQ_FIRST(&(cell->field->members));
+ ret = snprintf(pp, psize,
+ "M DEFINITIONS ::=\nBEGIN\n"
+ "v %s ::= %s\n"
+ "END\n",
+ type_expr->reference ?
+ type_expr->reference->components[0].name :
+ _asn1p_expr_type2string(type_expr->expr_type),
+ p
+ );
+ } else {
+ WARNING("asn1c only be able to parse TypeFieldSpec and FixedTypeValueFieldSpec. Failed when parsing %s at line %d\n", p, arg->expr->_lineno);
+ free(p); /* bad idea freeing object you refer to later! */
+ free(pp);
+ return -1;
+ }
+ DEBUG("ASN.1 :\n\n%s\n", pp);
+
+ assert(ret < psize);
+ psize = ret;
+
+ asn = asn1p_parse_buffer(pp, psize, A1P_NOFLAGS);
+ free(pp);
+ if(asn == NULL) {
+ FATAL("Cannot parse Setting token %s "
+ "at line %d",
+ p,
+ arg->expr->_lineno
+ );
+ free(p);
+ return -1;
+ } else {
+ mod = TQ_FIRST(&(asn->modules));
+ assert(mod);
+ expr = TQ_REMOVE(&(mod->members), next);
+ assert(expr);
+
+ free(expr->Identifier);
+ expr->module = arg->expr->module;
+ expr->_lineno = 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 {
- WARNING("asn1c is not yet able to parse arbitrary direct values; try converting %s at line %d to a reference.", p, arg->expr->_lineno);
- free(p);
- return 1;
+ expr->Identifier = p;
}
- } else {
- ref = asn1p_ref_new(arg->expr->_lineno);
- asn1p_ref_add_component(ref, p, RLT_UNKNOWN);
- assert(ref);
+ asn1p_delete(asn);
+ }
+
+ if(expr->reference &&
+ !asn1f_lookup_symbol(arg, arg->mod, expr->rhs_pspecs, expr->reference)) {
- expr = asn1f_lookup_symbol(arg, arg->mod, arg->expr->rhs_pspecs, ref);
- if(!expr) {
+ asn1p_ref_free(expr->reference);
+ new_ref = 0;
+ expr->reference = type_expr->reference;
+ if (asn1f_value_resolve(arg, expr, 0)) {
+ expr->reference = 0;
+ asn1p_expr_free(expr);
FATAL("Cannot find %s referenced by %s at line %d",
p, arg->expr->Identifier,
arg->expr->_lineno);
- asn1p_ref_free(ref);
- free(p);
+ free(p); /* freeing must happen *after* p was used in FATAL() */
return -1;
}
}
@@ -222,11 +314,43 @@ _asn1f_assign_cell_value(arg_t *arg, struct asn1p_ioc_row_s *row, struct asn1p_i
cell->field->Identifier, p, expr->Identifier);
cell->value = expr;
+ cell->new_ref = new_ref;
idLength = strlen(expr->Identifier);
if(row->max_identifier_length < idLength)
row->max_identifier_length = idLength;
+ if(expr->Identifier != p)
+ free(p);
+
return 0;
}
+static asn1p_wsyntx_chunk_t *
+asn1f_next_literal_chunk(asn1p_wsyntx_t *syntax, asn1p_wsyntx_chunk_t *chunk, uint8_t *buf)
+{
+ asn1p_wsyntx_chunk_t *next_chunk;
+
+ next_chunk = TQ_NEXT(chunk, next);
+ do {
+ if(next_chunk == (struct asn1p_wsyntx_chunk_s *)0) {
+ if(!syntax->parent)
+ break;
+ next_chunk = TQ_NEXT(syntax->parent, next);
+ } else if(next_chunk->type == WC_LITERAL) {
+ if(strstr((char *)buf, (char *)next_chunk->content.token))
+ break;
+ if(!syntax->parent)
+ break;
+ next_chunk = TQ_NEXT(syntax->parent, next);
+ } else if(next_chunk->type == WC_WHITESPACE) {
+ next_chunk = TQ_NEXT(next_chunk, next);
+ } else if(next_chunk->type == WC_OPTIONALGROUP) {
+ syntax = next_chunk->content.syntax;
+ next_chunk = TQ_FIRST(((&next_chunk->content.syntax->chunks)));
+ } else
+ break;
+ } while (next_chunk);
+
+ return next_chunk;
+}
diff --git a/libasn1fix/asn1fix_cws.h b/libasn1fix/asn1fix_cws.h
index 3d24f163..e998a28a 100644
--- a/libasn1fix/asn1fix_cws.h
+++ b/libasn1fix/asn1fix_cws.h
@@ -4,6 +4,7 @@
/*
* Parse class objects
*/
+int asn1f_check_class_object(arg_t *arg);
int asn1f_parse_class_object(arg_t *arg);
#endif /* ASN1FIX_CLASS_WITH_SYNTAX_H */
diff --git a/libasn1fix/asn1fix_derefv.c b/libasn1fix/asn1fix_derefv.c
index 5436d58b..3942d16c 100644
--- a/libasn1fix/asn1fix_derefv.c
+++ b/libasn1fix/asn1fix_derefv.c
@@ -48,6 +48,7 @@ asn1f_fix_dereference_defaults(arg_t *arg) {
child->marker.default_value=expr->marker.default_value;
ret = asn1f_fix_dereference_defaults(&tmparg);
expr->marker.default_value = child->marker.default_value;
+ child->marker.default_value = 0; /* ULB: trying to ensure there isn't another pointer to the same value object */
if(ret == 0) return 0; /* Finished */
}
diff --git a/libasn1fix/asn1fix_param.c b/libasn1fix/asn1fix_param.c
index f8e3a2e7..fe98081a 100644
--- a/libasn1fix/asn1fix_param.c
+++ b/libasn1fix/asn1fix_param.c
@@ -18,6 +18,7 @@ asn1f_parameterization_fork(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *rhs_ps
resolver_arg_t rarg; /* resolver argument */
asn1p_expr_t *exc; /* expr clone */
asn1p_expr_t *rpc; /* rhs_pspecs clone */
+ asn1p_expr_t *m; /* expr members */
void *p;
struct asn1p_pspec_s *pspec;
int npspecs;
@@ -69,6 +70,17 @@ asn1f_parameterization_fork(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *rhs_ps
pspec->my_clone = exc;
exc->spec_index = npspecs;
+ /* Passing arguments to members and type references */
+ exc->rhs_pspecs = expr->rhs_pspecs ? expr->rhs_pspecs : rhs_pspecs;
+ if(exc->rhs_pspecs)
+ exc->rhs_pspecs->ref_cnt++;
+
+ TQ_FOR(m, &exc->members, next) {
+ m->rhs_pspecs = exc->rhs_pspecs;
+ if (exc->rhs_pspecs)
+ exc->rhs_pspecs->ref_cnt++;
+ }
+
DEBUG("Forked new parameterization for %s", expr->Identifier);
/* Commit */
@@ -86,7 +98,15 @@ compare_specializations(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b) {
if(ac == bc) continue;
if(ac->meta_type != bc->meta_type) break;
if(ac->expr_type != bc->expr_type) break;
-
+ /* Maybe different object sets */
+ if(ac->constraints && bc->constraints
+ && ac->constraints->containedSubtype
+ && bc->constraints->containedSubtype
+ && ac->constraints->containedSubtype->type == ATV_REFERENCED
+ && bc->constraints->containedSubtype->type == ATV_REFERENCED
+ && strcmp(ac->constraints->containedSubtype->value.reference->components[0].name,
+ bc->constraints->containedSubtype->value.reference->components[0].name))
+ break;
if(!ac->reference && !bc->reference)
continue;
diff --git a/libasn1fix/asn1fix_retrieve.c b/libasn1fix/asn1fix_retrieve.c
index 52506b81..86540b94 100644
--- a/libasn1fix/asn1fix_retrieve.c
+++ b/libasn1fix/asn1fix_retrieve.c
@@ -287,14 +287,13 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspe
break;
}
if(ref_tc) {
+ /* It is acceptable that we don't use input parameters */
if(rhs_pspecs && !ref_tc->lhs_params) {
- FATAL("Parameterized type %s expected "
+ WARNING("Parameterized type %s expected "
"for %s at line %d",
ref_tc->Identifier,
asn1f_printable_reference(ref),
ref->_lineno);
- errno = EPERM;
- return NULL;
}
if(!rhs_pspecs && ref_tc->lhs_params) {
FATAL("Type %s expects specialization "
@@ -320,30 +319,33 @@ asn1f_lookup_symbol_impl(arg_t *arg, asn1p_module_t *mod, asn1p_expr_t *rhs_pspe
*/
{
/* Search inside standard module */
- static asn1p_oid_t *uioc_oid;
- if(!uioc_oid) {
- asn1p_oid_arc_t arcs[] = {
- { 1, "iso" },
- { 3, "org" },
- { 6, "dod" },
- { 1, "internet" },
- { 4, "private" },
- { 1, "enterprise" },
- { 9363, "spelio" },
- { 1, "software" },
- { 5, "asn1c" },
- { 3, "standard-modules" },
- { 0, "auto-imported" },
- { 1, 0 }
- };
+ asn1p_oid_t *uioc_oid;
+ asn1p_oid_arc_t arcs[] = {
+ { 1, "iso" },
+ { 3, "org" },
+ { 6, "dod" },
+ { 1, "internet" },
+ { 4, "private" },
+ { 1, "enterprise" },
+ { 9363, "spelio" },
+ { 1, "software" },
+ { 5, "asn1c" },
+ { 3, "standard-modules" },
+ { 0, "auto-imported" },
+ { 1, 0 }
+ };
+
+ if(!imports_from) {
uioc_oid = asn1p_oid_construct(arcs,
sizeof(arcs)/sizeof(arcs[0]));
- }
- if(!imports_from && (!mod->module_oid
- || asn1p_oid_compare(mod->module_oid, uioc_oid))) {
- imports_from = asn1f_lookup_module(arg,
- "ASN1C-UsefulInformationObjectClasses",
- uioc_oid);
+
+ if(!mod->module_oid
+ || asn1p_oid_compare(mod->module_oid, uioc_oid))
+ imports_from = asn1f_lookup_module(arg,
+ "ASN1C-UsefulInformationObjectClasses",
+ uioc_oid);
+
+ asn1p_oid_free(uioc_oid);
if(imports_from) goto importing;
}
}
@@ -430,10 +432,16 @@ asn1f_find_terminal_thing(arg_t *arg, asn1p_expr_t *expr, enum ftt_what what) {
*/
tc = asn1f_lookup_symbol(arg, expr->module, expr->rhs_pspecs, ref);
if(tc == NULL) {
- DEBUG("\tSymbol \"%s\" not found: %s",
- asn1f_printable_reference(ref),
- strerror(errno));
- return NULL;
+ /*
+ * Lookup inside the ref's module and its IMPORTS section.
+ */
+ tc = asn1f_lookup_symbol(arg, ref->module, expr->rhs_pspecs, ref);
+ if(tc == NULL) {
+ DEBUG("\tSymbol \"%s\" not found: %s",
+ asn1f_printable_reference(ref),
+ strerror(errno));
+ return NULL;
+ }
}
/*
diff --git a/libasn1fix/asn1fix_value.c b/libasn1fix/asn1fix_value.c
index 0e60ef7b..b881afca 100644
--- a/libasn1fix/asn1fix_value.c
+++ b/libasn1fix/asn1fix_value.c
@@ -199,8 +199,28 @@ asn1f_look_value_in_type(arg_t *arg,
: "<not found>"
);
- if(child_expr && child_expr->value) {
- if(_asn1f_copy_value(arg, value_expr, child_expr))
+ if(child_expr) {
+ /* Maybe hasn't been fixed yet. */
+ if (!child_expr->value) {
+ asn1p_expr_t *saved_expr = arg->expr;
+ arg->expr = type_expr;
+ switch (type_expr->expr_type) {
+ case ASN_BASIC_INTEGER:
+ asn1f_fix_integer(arg);
+ break;
+ case ASN_BASIC_ENUMERATED:
+ asn1f_fix_enum(arg);
+ break;
+ default:
+ WARNING("Unexpected type %s for %s",
+ type_expr->expr_type,
+ type_expr->Identifier);
+ return -1;
+ }
+ arg->expr = saved_expr;
+ }
+ if(child_expr->value && _asn1f_copy_value(arg,
+ value_expr, child_expr))
return -1;
/* Fall through */
}