mirror of https://gerrit.osmocom.org/asn1c
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:
parent
4e5edcf063
commit
50934ba3d4
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
|
|
Loading…
Reference in New Issue