diff options
author | Lev Walkin <vlm@lionet.info> | 2010-10-25 00:10:34 -0700 |
---|---|---|
committer | Lev Walkin <vlm@lionet.info> | 2010-10-25 00:10:34 -0700 |
commit | ffe79f445099764490217e07622f535b887b2c84 (patch) | |
tree | f9bad460af8fc9ddd11ddf28b696dbeebe618dec /libasn1fix/asn1fix_enum.c | |
parent | a6dd57a927459e7a517833d41ba3565057f9b859 (diff) |
Enumeration constraints relaxed
Diffstat (limited to 'libasn1fix/asn1fix_enum.c')
-rw-r--r-- | libasn1fix/asn1fix_enum.c | 72 |
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 |