Fix 'Information Object Set XXX contains no objects' when parsing S1AP's ASN.1

The aforementioned error message displayed during processing the following ASN.1 excerpt.

S1AP-ELEMENTARY-PROCEDURES S1AP-ELEMENTARY-PROCEDURE ::= {
    S1AP-ELEMENTARY-PROCEDURES-CLASS-1 |
    S1AP-ELEMENTARY-PROCEDURES-CLASS-2,
    ...
}

S1AP-ELEMENTARY-PROCEDURES-CLASS-1 S1AP-ELEMENTARY-PROCEDURE ::= {
    handoverPreparation                |
...
    writeReplaceWarning,
    ...,
    uERadioCapabilityMatch             |
....
    uEContextResume
}

S1AP-ELEMENTARY-PROCEDURES-CLASS-2 S1AP-ELEMENTARY-PROCEDURE ::= {
    handoverNotification               |
...
    privateMessage,
    ...,
    downlinkUEAssociatedLPPaTransport  |
...
    mMECPRelocationIndication
}

Because S1AP-ELEMENTARY-PROCEDURES-CLASS-1 and S1AP-ELEMENTARY-PROCEDURES-CLASS-2
are resolved 'after' S1AP-ELEMENTARY-PROCEDURES, so the ioc tables of them are not
available during resolving S1AP-ELEMENTARY-PROCEDURES. So we can not drop the
latter's containedSubtype field at first pass of asn1f_resolve_constraints of fix
process.

We also add second pass of asn1f_resolve_constraints to have a chance to combine
ioc tables of S1AP-ELEMENTARY-PROCEDURES-CLASS-1 and
S1AP-ELEMENTARY-PROCEDURES-CLASS-2.
This commit is contained in:
Bi-Ruei, Chiu 2017-09-11 08:50:59 +08:00 committed by Lev Walkin
parent 4e5edcf063
commit 50934ba3d4
4 changed files with 59 additions and 1 deletions

View File

@ -262,6 +262,12 @@ asn1f_fix_module__phase_2(arg_t *arg) {
ret = asn1f_recurse_expr(arg, asn1f_fix_dereference_defaults);
RET2RVAL(ret, rvalue);
/*
* Resolve references in constraints (the second pass).
*/
ret = asn1f_recurse_expr(arg, asn1f_resolve_constraints);
RET2RVAL(ret, rvalue);
/*
* Check semantic validity of constraints.
*/

View File

@ -21,6 +21,7 @@ asn1constraint_pullup(arg_t *arg) {
switch(expr->meta_type) {
case AMT_TYPE:
case AMT_TYPEREF:
case AMT_VALUESET:
break;
default:
return 0; /* Nothing to do */
@ -273,6 +274,7 @@ static int
constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct) {
asn1p_constraint_t *ct_expr;
int ret;
asn1p_expr_t *rtype = (asn1p_expr_t *)0;
DEBUG("(\"%s\")", asn1f_printable_value(ct->containedSubtype));
@ -280,7 +282,6 @@ constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct) {
ct_expr = ct->containedSubtype->value.constraint;
DEBUG("Found %s in constraints", "ValueSet");
} else if(get_reference_from(ct)) {
asn1p_expr_t *rtype;
arg_t tmparg;
rtype = asn1f_lookup_symbol(arg, arg->expr->rhs_pspecs,
@ -299,6 +300,14 @@ constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct) {
ret = asn1constraint_pullup(&tmparg);
if(ret) return ret;
if(rtype->ioc_table) {
if(!arg->expr->ioc_table)
arg->expr->ioc_table = asn1p_ioc_table_new();
asn1p_ioc_table_append(arg->expr->ioc_table, rtype->ioc_table);
asn1p_value_free(ct->containedSubtype);
ct->containedSubtype = NULL;
}
ct_expr = rtype->combined_constraints;
if(!ct_expr) return 0;
} else {
@ -330,6 +339,14 @@ constraint_type_resolve(arg_t *arg, asn1p_constraint_t *ct) {
}
ct->type = ACT_CA_SET;
/* keep constrainedSubtype field for future usage,
if valueset has not been resolved yet. */
if(rtype &&
(rtype->meta_type == AMT_VALUESET) &&
(!rtype->ioc_table))
return 0;
asn1p_value_free(ct->containedSubtype);
ct->containedSubtype = NULL;

View File

@ -25,6 +25,16 @@ asn1p_ioc_table_add(asn1p_ioc_table_t *it, asn1p_ioc_row_t *row) {
it->row[it->rows++] = row;
}
void
asn1p_ioc_table_append(asn1p_ioc_table_t *it, asn1p_ioc_table_t *src) {
if(!src) return;
for(size_t i = 0; i < src->rows; i++) {
asn1p_ioc_table_add(it, asn1p_ioc_row_clone(src->row[i]));
}
}
void
asn1p_ioc_table_free(asn1p_ioc_table_t *it) {
if(it) {
@ -93,6 +103,29 @@ asn1p_ioc_row_new(asn1p_expr_t *oclass) {
return row;
}
asn1p_ioc_row_t *
asn1p_ioc_row_clone(asn1p_ioc_row_t *src) {
asn1p_ioc_row_t *row;
row = calloc(1, sizeof *row);
if(!row) return NULL;
row->column = calloc(src->columns, sizeof *src->column);
if(!row->column) {
free(row);
return NULL;
}
row->columns = src->columns;
for(size_t i = 0; i < src->columns; i++) {
row->column[i].field = src->column[i].field;
row->column[i].value = src->column[i].value ? asn1p_expr_clone(src->column[i].value, 0) : 0;
row->column[i].new_ref = 1;
}
return row;
}
void
asn1p_ioc_row_delete(asn1p_ioc_row_t *row) {
if(row) {

View File

@ -16,6 +16,7 @@ typedef struct asn1p_ioc_row_s {
} asn1p_ioc_row_t;
asn1p_ioc_row_t *asn1p_ioc_row_new(struct asn1p_expr_s *oclass);
asn1p_ioc_row_t *asn1p_ioc_row_clone(asn1p_ioc_row_t *src);
size_t asn1p_ioc_row_max_identifier_length(asn1p_ioc_row_t *);
void asn1p_ioc_row_delete(asn1p_ioc_row_t *);
@ -27,6 +28,7 @@ typedef struct asn1p_ioc_table_s {
asn1p_ioc_table_t *asn1p_ioc_table_new(void);
void asn1p_ioc_table_add(asn1p_ioc_table_t *, asn1p_ioc_row_t *row);
void asn1p_ioc_table_append(asn1p_ioc_table_t *it, asn1p_ioc_table_t *src);
size_t asn1p_ioc_table_max_identifier_length(asn1p_ioc_table_t *);
void asn1p_ioc_table_free(asn1p_ioc_table_t *);