asn1: Basic validation of objects / object sets

- Validate that required value fields have values specified in objects

 - Validate that unique value fields have unique values within any
   object set
This commit is contained in:
Nicolas Williams
2021-02-26 14:48:22 -06:00
parent d128597cf7
commit 7f941b220b
4 changed files with 61 additions and 10 deletions

View File

@@ -743,12 +743,6 @@ For examples of X.681/X.682/X.683 usage, look at `lib/asn1/rfc2459.asn1`.
## Limitations
- Currently no effort is made to check the uniqueness of `UNIQUE` fields of
objects in object sets.
- Currently no effort is made to check that required fields are specified in
objects.
- `AtNotation` is very limited.
- Object set extensibility is not supported.

View File

@@ -60,6 +60,7 @@ static Field *new_type_field(char *, int, Type *);
static Field *new_fixed_type_value_field(char *, Type *, int, int, struct value *);
static Type *parametrize_type(Type *, IOSClass *);
static Type *type_from_class_field(IOSClass *, const char *);
static void validate_object_set(IOSObjectSet *);
/*static Type *type_from_object(const char *, const char *);*/
static struct constraint_spec *new_constraint_spec(enum ctype);
static Type *new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype);
@@ -499,6 +500,7 @@ ObjectSetAssignment
s->objectset = $4;
s->objectset->symbol = s->objectset->symbol ? s->objectset->symbol : s;
s->objectset->iosclass = $2;
validate_object_set($4);
generate_template_objectset_forwards(s);
}
;
@@ -1906,3 +1908,60 @@ type_from_class_field(IOSClass *c, const char *n)
}
return NULL;
}
static void
validate_object_set(IOSObjectSet *os)
{
IOSObject **objects;
ObjectField *of;
IOSObject *o;
Field *cf;
size_t nobjs, i;
/* Check unique fields */
HEIM_TAILQ_FOREACH(cf, os->iosclass->fields, fields) {
if (!cf->unique)
continue;
if (!cf->type)
errx(1, "Type fields of classes can't be UNIQUE (%s)",
os->iosclass->symbol->name);
sort_object_set(os, cf, &objects, &nobjs);
for (i = 0; i < nobjs; i++) {
HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
if (strcmp(cf->name, of->name))
continue;
if (!of->value)
errx(1, "Value not specified for required UNIQUE field %s of object %s",
cf->name, objects[i]->symbol->name);
break;
}
if (i == 0)
continue;
if (object_cmp(&objects[i - 1], &objects[i]) == 0)
errx(1, "Duplicate values of UNIQUE field %s of objects %s and %s",
cf->name, objects[i - 1]->symbol->name,
objects[i]->symbol->name);
}
free(objects);
}
/* Check required fields */
HEIM_TAILQ_FOREACH(cf, os->iosclass->fields, fields) {
if (cf->optional || cf->defval || !cf->type)
continue;
HEIM_TAILQ_FOREACH(o, os->objects, objects) {
int specified = 0;
HEIM_TAILQ_FOREACH(of, o->objfields, objfields) {
if (strcmp(of->name, cf->name))
continue;
if (of->value)
specified = 1;
break;
}
if (!specified)
errx(1, "Value not specified for required non-UNIQUE field %s of object %s",
cf->name, o->symbol->name);
}
}
}

View File

@@ -148,7 +148,7 @@ void close_codefile(void);
void get_open_type_defn_fields(const Type *, Member **, Member **, Field **,
Field **, int *);
void sort_object_set(IOSObjectSet *, Field *, IOSObject ***, size_t *);
int object_cmp(const void *, const void *);
int is_template_compat (const Symbol *);
void generate_template(const Symbol *);

View File

@@ -689,7 +689,7 @@ objid_cmp(struct objid *oida, struct objid *oidb)
return -1;
}
static int
int
object_cmp(const void *va, const void *vb)
{
const IOSObject *oa = *(const IOSObject * const *)va;
@@ -727,8 +727,6 @@ sort_object_set(IOSObjectSet *os, /* Object set to sort fields of */
IOSObject *o;
size_t i, nobjs = 0;
/* FIXME: This would be a good place to check field UNIQUE constraints */
HEIM_TAILQ_FOREACH(o, os->objects, objects) {
ObjectField *typeidobjf = NULL;
ObjectField *of;