aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2004-08-25 02:05:28 +0000
committerLev Walkin <vlm@lionet.info>2004-08-25 02:05:28 +0000
commitb74ac57b436361a7e82a49af5b1eb8c5f47dc310 (patch)
treecc35dc654f91ea8aeafcf677e02ae118e1bd2710
parentb9fa780e7b80e497147b243335b0e76582e7b227 (diff)
introducing less strict semantics
-rw-r--r--libasn1fix/asn1fix_constraint_compat.c60
-rw-r--r--libasn1fix/asn1fix_crange.c189
-rw-r--r--libasn1fix/asn1fix_crange.h10
3 files changed, 200 insertions, 59 deletions
diff --git a/libasn1fix/asn1fix_constraint_compat.c b/libasn1fix/asn1fix_constraint_compat.c
index f2f47fd1..effa0ad5 100644
--- a/libasn1fix/asn1fix_constraint_compat.c
+++ b/libasn1fix/asn1fix_constraint_compat.c
@@ -88,17 +88,21 @@ asn1constraint_compatible(asn1p_expr_type_e expr_type,
}
-#define DECL(foo, val1, val2) \
+#define DECL_RANGE(foo, val1, val2, pv) \
static asn1cnst_range_t range_ ## foo = { \
{ ARE_VALUE, 0, val1 }, \
{ ARE_VALUE, 0, val2 }, \
- 0, 0, 0, 0, 0, 0 }
+ 0, 0, 0, 0, 0, 0, pv }
+
+#define DECL(foo, val1, val2) DECL_RANGE(foo, val1, val2, 0)
+#define DECL_notPV(foo, val1, val2) DECL_RANGE(foo, val1, val2, 1)
asn1cnst_range_t *
asn1constraint_default_alphabet(asn1p_expr_type_e expr_type) {
+ DECL_notPV(octstr, 0x00, 0xff); /* Not PER-visible */
+ DECL_notPV(utf8, 0x00, 0x7fffffff); /* Not PER-visible */
+ DECL(bmp, 0x00, 65533); /* 64K-2 cells */
DECL(uint7, 0x00, 0x7f);
- DECL(uint8, 0x00, 0xff);
- DECL(uint16, 0x00, 0xffff);
DECL(uint31, 0x00, 0x7fffffff);
DECL(Space, 0x20, 0x20);
DECL(ApostropheAndParens, 0x27, 0x29);
@@ -127,38 +131,43 @@ asn1constraint_default_alphabet(asn1p_expr_type_e expr_type) {
&range_Plus, &range_MinusDot, &range_Digits, &range_Z };
static asn1cnst_range_t *range_GeneralizedTime_array[] = {
&range_PlusCommaMinusDot, &range_Digits, &range_Z };
+
+ static asn1cnst_range_t range_notPERVisible = {
+ { ARE_MIN, 0, 0 },
+ { ARE_MAX, 0, 0 },
+ 0, 0, 0, 0, 0, 0, 1 };
static asn1cnst_range_t range_NumericString = {
{ ARE_VALUE, 0, 0x20 },
{ ARE_VALUE, 0, 0x39 },
range_NumericString_array,
sizeof(range_NumericString_array)
/sizeof(range_NumericString_array[0]),
- 0, 0, 0, 0 };
+ 0, 0, 0, 0, 0 };
static asn1cnst_range_t range_PrintableString = {
{ ARE_VALUE, 0, 0x20 },
{ ARE_VALUE, 0, 0x7a },
range_PrintableString_array,
sizeof(range_PrintableString_array)
/sizeof(range_PrintableString_array[0]),
- 0, 0, 0, 0 };
+ 0, 0, 0, 0, 0 };
static asn1cnst_range_t range_VisibleString = {
{ ARE_VALUE, 0, 0x20 },
{ ARE_VALUE, 0, 0x7e },
- 0, 0, 0, 0, 0, 0 };
+ 0, 0, 0, 0, 0, 0, 0 };
static asn1cnst_range_t range_UTCTime = {
{ ARE_VALUE, 0, 0x2b },
{ ARE_VALUE, 0, 0x5a },
range_UTCTime_array,
sizeof(range_UTCTime_array)
/sizeof(range_UTCTime_array[0]),
- 0, 0, 0, 0 };
+ 0, 0, 0, 0, 1 };
static asn1cnst_range_t range_GeneralizedTime = {
{ ARE_VALUE, 0, 0x2b },
{ ARE_VALUE, 0, 0x5a },
range_GeneralizedTime_array,
sizeof(range_GeneralizedTime_array)
/sizeof(range_GeneralizedTime_array[0]),
- 0, 0, 0, 0 };
+ 0, 0, 0, 0, 1 };
switch(expr_type) {
case ASN_STRING_NumericString:
@@ -169,19 +178,42 @@ asn1constraint_default_alphabet(asn1p_expr_type_e expr_type) {
return &range_VisibleString;
case ASN_STRING_IA5String:
return &range_uint7;
- case ASN_BASIC_OCTET_STRING:
- return &range_uint8;
case ASN_STRING_BMPString:
- return &range_uint16;
- case ASN_STRING_UniversalString:
+ return &range_bmp;
case ASN_STRING_UTF8String:
+ /*
+ * X.691, #9.3.6
+ * Not a known-multipler character string type.
+ */
+ assert(range_utf8.not_PER_visible);
+ return &range_utf8;
+ case ASN_STRING_UniversalString:
return &range_uint31;
case ASN_BASIC_UTCTime:
+ /* Permitted alphabet constraint is not applicable */
+ assert(range_UTCTime.not_PER_visible);
return &range_UTCTime;
case ASN_BASIC_GeneralizedTime:
+ /* Permitted alphabet constraint is not applicable */
+ assert(range_GeneralizedTime.not_PER_visible);
return &range_GeneralizedTime;
+ case ASN_BASIC_OCTET_STRING:
+ /*
+ * Permitted alphabet constraint is not applicable
+ * to this type. However, we support it, albeit not
+ * in a strict PER mode.
+ */
+ assert(range_octstr.not_PER_visible);
+ return &range_octstr;
default:
- break;
+ if(!(expr_type & ASN_STRING_MASK))
+ break;
+ assert(expr_type & ASN_STRING_NKM_MASK);
+ /*
+ * X.691, 9.3.6
+ * Not a known-multiplier character string.
+ */
+ return &range_notPERVisible;
}
return NULL;
diff --git a/libasn1fix/asn1fix_crange.c b/libasn1fix/asn1fix_crange.c
index 3032799b..6ef8c8ac 100644
--- a/libasn1fix/asn1fix_crange.c
+++ b/libasn1fix/asn1fix_crange.c
@@ -167,11 +167,20 @@ _range_print(const asn1cnst_range_t *range) {
if(_edge_compare(&range->left, &range->right)) {
printf("(%s.", _edge_value(&range->left));
- printf(".%s)", _edge_value(&range->right));
+ printf(".%s", _edge_value(&range->right));
} else {
- printf("(%s)", _edge_value(&range->left));
+ printf("(%s", _edge_value(&range->left));
}
+ if(range->extensible) {
+ printf(",...)");
+ } else {
+ printf(")");
+ }
+
+ if(range->incompatible) printf("/I");
+ if(range->not_PER_visible) printf("/!V");
+
if(range->el_count) {
int i;
printf("-=>");
@@ -232,6 +241,9 @@ static int _range_merge_in(asn1cnst_range_t *into, asn1cnst_range_t *cr) {
int prev_count = into->el_count;
int i;
+ into->not_PER_visible |= cr->not_PER_visible;
+ into->extensible |= cr->extensible;
+
/*
* Add the element OR all its children "into".
*/
@@ -481,8 +493,15 @@ _range_intersection(asn1cnst_range_t *range, const asn1cnst_range_t *with, int s
int ret;
int i, j;
- if(with->empty_constraint || range->empty_constraint) {
- range->empty_constraint = 1; /* Propagate error */
+ assert(!range->incompatible);
+
+ /* Propagate errors */
+ range->extensible |= with->extensible;
+ range->not_PER_visible |= with->not_PER_visible;
+ range->empty_constraint |= with->empty_constraint;
+
+ if(range->empty_constraint) {
+ /* No use in intersecting empty constraints */
return 0;
}
@@ -609,7 +628,7 @@ _range_union(asn1cnst_range_t *range) {
* Still, range may be joined: (1..4)(5..10).
* This logic is valid only for whole numbers
* (i.e., not REAL type, but REAL constraints
- * are not PER-visible (X.691, 9.3.12).
+ * are not PER-visible (X.691, #9.3.12).
*/
if(ra->right.type == ARE_VALUE
&& rb->left.type == ARE_VALUE
@@ -674,7 +693,7 @@ _range_canonicalize(asn1cnst_range_t *range) {
}
asn1cnst_range_t *
-asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constraint_t *ct, enum asn1p_constraint_type_e type, const asn1cnst_range_t *minmax, int *exmet) {
+asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constraint_t *ct, enum asn1p_constraint_type_e type, const asn1cnst_range_t *minmax, int *exmet, int strict_PV) {
asn1cnst_range_t *range;
asn1cnst_range_t *tmp;
asn1p_value_t *vmin;
@@ -689,7 +708,8 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
}
/*
- * Check if the requested constraint is compatible with expression type.
+ * Check if the requested constraint is theoretically compatible
+ * with the given expression type.
*/
if(asn1constraint_compatible(expr_type, type) != 1) {
errno = EINVAL;
@@ -730,7 +750,15 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
range = _range_new();
}
- if(!ct || range->not_PER_visible)
+ /*
+ * X.691, #9.3.6
+ * Constraints on restricter character string types
+ * which are not known-multiplier are not PER-visible.
+ */
+ if((expr_type & ASN_STRING_NKM_MASK))
+ range->not_PER_visible = 1;
+
+ if(!ct || (strict_PV && range->not_PER_visible))
return range;
switch(ct->type) {
@@ -746,9 +774,11 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
break;
case ACT_EL_EXT:
if(!*exmet) {
- range->not_PER_visible = 1;
+ range->incompatible = 1;
} else {
- range->extensible = 1;
+ _range_free(range);
+ errno = ERANGE;
+ range = 0;
}
return range;
case ACT_CT_SIZE:
@@ -756,12 +786,24 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
if(type == ct->type) {
*exmet = 1;
} else {
- range->not_PER_visible = 1;
+ range->incompatible = 1;
return range;
}
assert(ct->el_count == 1);
- return asn1constraint_compute_PER_range(expr_type,
- ct->elements[0], type, minmax, exmet);
+ tmp = asn1constraint_compute_PER_range(expr_type,
+ ct->elements[0], type, minmax, exmet, strict_PV);
+ if(tmp) {
+ _range_free(range);
+ } else {
+ if(errno == ERANGE) {
+ range->empty_constraint = 1;
+ range->extensible = 1;
+ tmp = range;
+ } else {
+ _range_free(range);
+ }
+ }
+ return tmp;
case ACT_CA_SET: /* (10..20)(15..17) */
case ACT_CA_INT: /* SIZE(1..2) ^ FROM("ABCD") */
@@ -769,13 +811,29 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
for(i = 0; i < ct->el_count; i++) {
tmp = asn1constraint_compute_PER_range(expr_type,
ct->elements[i], type,
- ct->type==ACT_CA_SET?range:minmax, exmet);
+ ct->type==ACT_CA_SET?range:minmax, exmet,
+ strict_PV);
if(!tmp) {
- _range_free(range);
- return NULL;
+ if(errno == ERANGE) {
+ continue;
+ } else {
+ _range_free(range);
+ return NULL;
+ }
}
- if(tmp->not_PER_visible) {
+ if(tmp->incompatible) {
+ /*
+ * Ignore constraints
+ * incompatible with arguments:
+ * SIZE(1..2) ^ FROM("ABCD")
+ * either SIZE or FROM will be ignored.
+ */
+ _range_free(tmp);
+ continue;
+ }
+
+ if(strict_PV && tmp->not_PER_visible) {
if(ct->type == ACT_CA_SET) {
/*
* X.691, #9.3.18:
@@ -791,17 +849,6 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
continue;
}
- range->extensible |= tmp->extensible;
-
- if(tmp->extensible && type == ACT_CT_FROM) {
- /*
- * X.691, #9.3.10:
- * Extensible permitted alphabet constraints
- * are not PER-visible.
- */
- range->not_PER_visible = 1;
- }
-
ret = _range_intersection(range, tmp,
ct->type == ACT_CA_SET);
_range_free(tmp);
@@ -817,40 +864,100 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
case ACT_CA_CSV: /* SIZE(1..2, 3..4) */
case ACT_CA_UNI: /* SIZE(1..2) | FROM("ABCD") */
- /* Merge everything. Canonicalizator will do union magic */
+ /*
+ * Grab the first valid constraint.
+ */
+ tmp = 0;
for(i = 0; i < ct->el_count; i++) {
tmp = asn1constraint_compute_PER_range(expr_type,
- ct->elements[i], type, minmax, exmet);
+ ct->elements[i], type, minmax, exmet,
+ strict_PV);
if(!tmp) {
- _range_free(range);
- return NULL;
+ if(errno == ERANGE) {
+ range->extensible = 1;
+ continue;
+ } else {
+ _range_free(range);
+ return NULL;
+ }
+ }
+ if(tmp->incompatible) {
+ _range_free(tmp);
+ tmp = 0;
+ }
+ break;
+ }
+ if(tmp) {
+ tmp->extensible |= range->extensible;
+ tmp->empty_constraint |= range->empty_constraint;
+ _range_free(range);
+ range = tmp;
+ } else {
+ range->incompatible = 1;
+ return range;
+ }
+
+ /*
+ * Merge with the rest of them.
+ * Canonicalizator will do the union magic.
+ */
+ for(; i < ct->el_count; i++) {
+ tmp = asn1constraint_compute_PER_range(expr_type,
+ ct->elements[i], type, minmax, exmet,
+ strict_PV);
+ if(!tmp) {
+ if(errno == ERANGE) {
+ range->extensible = 1;
+ continue;
+ } else {
+ _range_free(range);
+ return NULL;
+ }
+ }
+
+ if(tmp->incompatible) {
+ _range_free(tmp);
+ _range_canonicalize(range);
+ range->incompatible = 1;
+ return range;
}
if(tmp->empty_constraint) {
- /* Ignore empty constraints */
+ /*
+ * Ignore empty constraints in OR logic.
+ */
+ range->extensible |= tmp->extensible;
_range_free(tmp);
continue;
}
- range->not_PER_visible |= tmp->not_PER_visible;
- range->extensible |= tmp->extensible;
-
_range_merge_in(range, tmp);
}
_range_canonicalize(range);
- if(range->not_PER_visible) {
+ if(range->extensible && type == ACT_CT_FROM) {
+ /*
+ * X.691, #9.3.10:
+ * Extensible permitted alphabet constraints
+ * are not PER-visible.
+ */
+ range->not_PER_visible = 1;
+ }
+
+ if(strict_PV && range->not_PER_visible) {
/*
* X.691, #9.3.19:
* If not PER-visible constraint is part of UNION,
- * the resulting constraint is not PER-visible.
+ * the whole resulting constraint is not PER-visible.
*/
_range_free(range);
if(minmax)
range = _range_clone(minmax);
else
range = _range_new();
+ range->not_PER_visible = 1;
+ range->incompatible = 1;
}
return range;
@@ -862,10 +969,10 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
assert(ct->el_count >= 1);
_range_free(range);
range = asn1constraint_compute_PER_range(expr_type,
- ct->elements[0], type, minmax, exmet);
+ ct->elements[0], type, minmax, exmet, strict_PV);
return range;
default:
- range->not_PER_visible = 1;
+ range->incompatible = 1;
return range;
}
@@ -874,7 +981,7 @@ asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constr
/*
* Expectation is not met. Return the default range.
*/
- range->not_PER_visible = 1;
+ range->incompatible = 1;
return range;
}
diff --git a/libasn1fix/asn1fix_crange.h b/libasn1fix/asn1fix_crange.h
index 9873e3b2..9d4763ac 100644
--- a/libasn1fix/asn1fix_crange.h
+++ b/libasn1fix/asn1fix_crange.h
@@ -21,13 +21,14 @@ typedef struct asn1cnst_range_s {
int el_size;
int empty_constraint; /* If yes, too bad. */
- int extensible; /* Extension marker (...) present. */
+ int extensible; /* Extension marker (...) is in effect. */
- int not_PER_visible; /* Contains non PER-visible components */
+ int incompatible; /* Constraint incompatible with argument */
+ int not_PER_visible; /* Contains not PER-visible components */
} asn1cnst_range_t;
/*
- * Compute the PER-visible constraint range.
+ * Compute the constraint range with variable PER visibility restrictions.
*
* (expr_type) must have the type of the top-level parent ASN.1 type.
* (required_type) must be one of ACT_EL_RANGE, ACT_CT_SIZE or ACT_CT_FROM.
@@ -41,7 +42,8 @@ asn1cnst_range_t *asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type,
const asn1p_constraint_t *ct,
enum asn1p_constraint_type_e required_type,
const asn1cnst_range_t *minmax,
- int *expectation_met);
+ int *expectation_met,
+ int strict_PER_visibility);
void asn1constraint_range_free(asn1cnst_range_t *);
/*