aboutsummaryrefslogtreecommitdiffstats
path: root/libasn1fix/asn1fix_enum.c
diff options
context:
space:
mode:
authorLev Walkin <vlm@lionet.info>2010-10-25 00:10:34 -0700
committerLev Walkin <vlm@lionet.info>2010-10-25 00:10:34 -0700
commitffe79f445099764490217e07622f535b887b2c84 (patch)
treef9bad460af8fc9ddd11ddf28b696dbeebe618dec /libasn1fix/asn1fix_enum.c
parenta6dd57a927459e7a517833d41ba3565057f9b859 (diff)
Enumeration constraints relaxed
Diffstat (limited to 'libasn1fix/asn1fix_enum.c')
-rw-r--r--libasn1fix/asn1fix_enum.c72
1 files changed, 63 insertions, 9 deletions
diff --git a/libasn1fix/asn1fix_enum.c b/libasn1fix/asn1fix_enum.c
index 570d23ae..399cb625 100644
--- a/libasn1fix/asn1fix_enum.c
+++ b/libasn1fix/asn1fix_enum.c
@@ -8,15 +8,27 @@ asn1f_fix_enum(arg_t *arg) {
asn1p_expr_t *expr = arg->expr;
asn1p_expr_t *ev;
asn1c_integer_t max_value = -1;
+ asn1c_integer_t max_value_ext = -1;
int rvalue = 0;
asn1p_expr_t *ext_marker = NULL; /* "..." position */
int ret;
+ /* Keep track of value collisions */
+ asn1c_integer_t *used_vals;
+ int used_vals_sz = 50;
+ int used_vals_next = 0;
+
if(expr->expr_type != ASN_BASIC_ENUMERATED)
return 0; /* Just ignore it */
DEBUG("(%s)", expr->Identifier);
+ used_vals = (asn1c_integer_t *) malloc(sizeof(asn1c_integer_t) * used_vals_sz);
+ if (!used_vals) {
+ FATAL("Out of memory");
+ return -1;
+ }
+
/*
* 1. Scan the enumeration values in search for inconsistencies.
*/
@@ -93,12 +105,16 @@ asn1f_fix_enum(arg_t *arg) {
/*
* 1.3 Check the applicability of this value.
*/
- if(eval <= max_value) {
- if(ext_marker) {
- /*
- * Enumeration is allowed to be unordered
- * before the first marker.
- */
+
+ /*
+ * Enumeration is allowed to be unordered
+ * before the first marker, but after the marker
+ * the values must be ordered.
+ */
+ if (ext_marker) {
+ if (eval > max_value_ext) {
+ max_value_ext = eval;
+ } else {
FATAL(
"Enumeration %s at line %d: "
"Explicit value \"%s(%" PRIdASN ")\" "
@@ -108,21 +124,59 @@ asn1f_fix_enum(arg_t *arg) {
ev->_lineno,
ev->Identifier,
eval,
- max_value);
+ max_value_ext);
rvalue = -1;
}
- } else if(eval > max_value) {
+ }
+
+ if (eval > max_value) {
max_value = eval;
}
+
+ /*
+ * 1.4 Check that all identifiers are unique
+ */
+ int unique = 1;
+ int uv_idx;
+ for (uv_idx = 0; uv_idx < used_vals_next; uv_idx++) {
+ if (used_vals[uv_idx] == eval) {
+ FATAL(
+ "Enumeration %s at line %d: "
+ "Explicit value \"%s(%" PRIdASN ")\" "
+ "collides with previous values",
+ expr->Identifier,
+ ev->_lineno,
+ ev->Identifier,
+ eval);
+ rvalue = -1;
+ unique = 0;
+ }
+ }
+
+ if (unique) {
+ /* Grow the array if needed */
+ if (used_vals_next >= used_vals_sz) {
+ asn1c_integer_t *temp;
+ int new_sz = used_vals_sz + 50;
+ temp = (asn1c_integer_t *) realloc(used_vals,
+ sizeof(asn1c_integer_t) * new_sz);
+ if (!temp) return -1;
+ used_vals = temp;
+ used_vals_sz = new_sz;
+ }
+ used_vals[used_vals_next++] = eval;
+ }
+
/*
- * 1.4 Check that all identifiers before the current one
+ * 1.5 Check that all identifiers before the current one
* differs from it.
*/
ret = asn1f_check_unique_expr_child(arg, ev, 0, "identifier");
RET2RVAL(ret, rvalue);
}
+ free(used_vals);
/*
* 2. Reorder the first half (before optional "...") of the