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:
@@ -743,12 +743,6 @@ For examples of X.681/X.682/X.683 usage, look at `lib/asn1/rfc2459.asn1`.
|
|||||||
|
|
||||||
## Limitations
|
## 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.
|
- `AtNotation` is very limited.
|
||||||
|
|
||||||
- Object set extensibility is not supported.
|
- Object set extensibility is not supported.
|
||||||
|
@@ -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 Field *new_fixed_type_value_field(char *, Type *, int, int, struct value *);
|
||||||
static Type *parametrize_type(Type *, IOSClass *);
|
static Type *parametrize_type(Type *, IOSClass *);
|
||||||
static Type *type_from_class_field(IOSClass *, const char *);
|
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 Type *type_from_object(const char *, const char *);*/
|
||||||
static struct constraint_spec *new_constraint_spec(enum ctype);
|
static struct constraint_spec *new_constraint_spec(enum ctype);
|
||||||
static Type *new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype);
|
static Type *new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype);
|
||||||
@@ -499,6 +500,7 @@ ObjectSetAssignment
|
|||||||
s->objectset = $4;
|
s->objectset = $4;
|
||||||
s->objectset->symbol = s->objectset->symbol ? s->objectset->symbol : s;
|
s->objectset->symbol = s->objectset->symbol ? s->objectset->symbol : s;
|
||||||
s->objectset->iosclass = $2;
|
s->objectset->iosclass = $2;
|
||||||
|
validate_object_set($4);
|
||||||
generate_template_objectset_forwards(s);
|
generate_template_objectset_forwards(s);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@@ -1906,3 +1908,60 @@ type_from_class_field(IOSClass *c, const char *n)
|
|||||||
}
|
}
|
||||||
return NULL;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -148,7 +148,7 @@ void close_codefile(void);
|
|||||||
void get_open_type_defn_fields(const Type *, Member **, Member **, Field **,
|
void get_open_type_defn_fields(const Type *, Member **, Member **, Field **,
|
||||||
Field **, int *);
|
Field **, int *);
|
||||||
void sort_object_set(IOSObjectSet *, Field *, IOSObject ***, size_t *);
|
void sort_object_set(IOSObjectSet *, Field *, IOSObject ***, size_t *);
|
||||||
|
int object_cmp(const void *, const void *);
|
||||||
|
|
||||||
int is_template_compat (const Symbol *);
|
int is_template_compat (const Symbol *);
|
||||||
void generate_template(const Symbol *);
|
void generate_template(const Symbol *);
|
||||||
|
@@ -689,7 +689,7 @@ objid_cmp(struct objid *oida, struct objid *oidb)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
object_cmp(const void *va, const void *vb)
|
object_cmp(const void *va, const void *vb)
|
||||||
{
|
{
|
||||||
const IOSObject *oa = *(const IOSObject * const *)va;
|
const IOSObject *oa = *(const IOSObject * const *)va;
|
||||||
@@ -727,8 +727,6 @@ sort_object_set(IOSObjectSet *os, /* Object set to sort fields of */
|
|||||||
IOSObject *o;
|
IOSObject *o;
|
||||||
size_t i, nobjs = 0;
|
size_t i, nobjs = 0;
|
||||||
|
|
||||||
/* FIXME: This would be a good place to check field UNIQUE constraints */
|
|
||||||
|
|
||||||
HEIM_TAILQ_FOREACH(o, os->objects, objects) {
|
HEIM_TAILQ_FOREACH(o, os->objects, objects) {
|
||||||
ObjectField *typeidobjf = NULL;
|
ObjectField *typeidobjf = NULL;
|
||||||
ObjectField *of;
|
ObjectField *of;
|
||||||
|
Reference in New Issue
Block a user