#include "asn1fix_internal.h" int asn1f_fix_bit_string_value(arg_t *arg, asn1p_expr_t *ttype); static void asn1f_BS_remove_trailing_zero_bits(asn1p_value_t *value); static int asn1f_BS_unparsed_convert(arg_t *arg, asn1p_value_t *value, asn1p_expr_t *ttype); int asn1f_fix_bit_string(arg_t *arg) { asn1p_expr_t *expr = arg->expr; int r_value = 0; int ret; if(expr->meta_type == AMT_VALUE) { asn1p_expr_t *ttype; DEBUG("%s(%s) for line %d", __func__, expr->Identifier, expr->_lineno); ttype = asn1f_find_terminal_type(arg, expr, 0); if(ttype && ttype->expr_type == ASN_BASIC_BIT_STRING) { ret = asn1f_fix_bit_string_value(arg, ttype); RET2RVAL(ret, r_value); } } return r_value; } int asn1f_fix_bit_string_value(arg_t *arg, asn1p_expr_t *ttype) { asn1p_expr_t *expr = arg->expr; int r_value = 0; DEBUG("%s(%s) for line %d", __func__, expr->Identifier, expr->_lineno); switch(expr->value->type) { case ATV_UNPARSED: /* * Most definitely we have something like * value BitStringType1 ::= { a, b, c } * which could not be parsed by the LALR parser, mostly * because it requires knowledge about BitStringType1 * during the parsing. So, here's a little hack: we create * a buffer containing the full specification of a module, * which contains some pre-defined INTEGER type with the * opaque definition "{ a, b, c }" from the bit string. */ if(asn1f_BS_unparsed_convert(arg, expr->value, ttype)) { r_value = -1; break; } /* Fall through: remove trailing zero bits */ case ATV_BITVECTOR: asn1f_BS_remove_trailing_zero_bits(expr->value); break; default: break; } return r_value; } static void asn1f_BS_remove_trailing_zero_bits(asn1p_value_t *value) { int lmfb = -1; /* Last meaningful byte position */ int bits; /* Number of bits in the BIT STRING value */ int b; assert(value->type == ATV_BITVECTOR); bits = value->value.binary_vector.size_in_bits; /* * Figure out the rightmost meaningful byte. */ for(b = 0; b < ((bits + 7) >> 3); b++) { uint8_t uc = value->value.binary_vector.bits[b]; if(uc && b > lmfb) lmfb = b; } if(lmfb == -1) { bits = 0; } else { uint8_t uc; uc = value->value.binary_vector.bits[lmfb]; bits = (lmfb+1) * 8; /* * Squeeze the bit string width until the rightmost * bit is set. */ for(; uc && (uc & 1) == 0; uc >>= 1) bits--; if(uc == 0) { bits = lmfb * 8; } } value->value.binary_vector.size_in_bits = bits; } static int asn1f_BS_unparsed_convert(arg_t *arg, asn1p_value_t *value, asn1p_expr_t *ttype) { asn1p_t *asn; asn1p_module_t *mod; asn1p_expr_t *V; asn1p_expr_t *bit; asn1_integer_t aI; uint8_t *bitbuf; int bits; int psize; char *p; int ret; int r_value = 0; assert(value->type == ATV_UNPARSED); psize = value->value.string.size + 64; p = malloc(psize); if(p == NULL) return -1; ret = snprintf(p, psize, "M DEFINITIONS ::=\nBEGIN\n" "V ::= INTEGER %s\n" "END\n", value->value.string.buf ); assert(ret < psize); psize = ret; asn = asn1p_parse_buffer(p, psize, A1P_NOFLAGS); free(p); if(asn == NULL) { FATAL("Cannot parse BIT STRING value %s " "defined as %s at line %d", arg->expr->Identifier, value->value.string.buf, arg->expr->_lineno ); return -1; } mod = TQ_FIRST(&(asn->modules)); assert(mod); V = TQ_FIRST(&(mod->members)); assert(V); assert(strcmp(V->Identifier, "V") == 0); assert(TQ_FIRST(&(V->members))); /* * Simple loop just to fetch the maximal bit position * out of the BIT STRING value defined as NamedBitList. */ aI = -1; TQ_FOR(bit, &(V->members), next) { asn1p_expr_t *bitdef; bitdef = asn1f_lookup_child(ttype, bit->Identifier); if(bitdef && bitdef->value && bitdef->value->type == ATV_INTEGER) { if(bitdef->value->value.v_integer > aI) aI = bitdef->value->value.v_integer; } } if(aI > 1024 * 1024 * 8) { /* One megabyte */ FATAL("Unsupportedly large BIT STRING value \"%s\" " "defined at line %d " "(larger than 1MByte)", arg->expr->Identifier, arg->expr->_lineno ); asn1p_free(asn); return -1; } bits = aI + 1; /* Number of bits is more than a last bit position */ bitbuf = calloc(1, 1 + ((bits + 7) / 8)); if(bitbuf == NULL) { asn1p_free(asn); return -1; } TQ_FOR(bit, &(V->members), next) { asn1p_expr_t *bitdef; int set_bit_pos; if(bit->value) { WARNING("Identifier \"%s\" at line %d " "must not have a value", bit->Identifier, bit->_lineno); RET2RVAL(1, r_value); } bitdef = asn1f_lookup_child(ttype, bit->Identifier); if(bitdef == NULL) { FATAL("Identifier \"%s\" at line %d is not defined " "in the \"%s\" type definition at line %d", bit->Identifier, bit->_lineno, ttype->Identifier, ttype->_lineno ); RET2RVAL(-1, r_value); continue; } if(bitdef->value == NULL || bitdef->value->type != ATV_INTEGER) { FATAL("Broken identifier " "\"%s\" at line %d " "referenced by \"%s\" at line %d", bitdef->Identifier, bitdef->_lineno, arg->expr->Identifier, arg->expr->_lineno ); RET2RVAL(-1, r_value); continue; } assert(bitdef->value->value.v_integer < bits); set_bit_pos = bitdef->value->value.v_integer; bitbuf[set_bit_pos>>3] |= 1 << (7-(set_bit_pos % 8)); } asn1p_free(asn); free(value->value.string.buf); value->type = ATV_BITVECTOR; value->value.binary_vector.bits = bitbuf; value->value.binary_vector.size_in_bits = bits; return r_value; }