Esempio n. 1
0
static void
asn1constraint_range_free_outer(asn1cnst_range_t *cr) {
	if(cr) {
		int i;
		if(cr->elements) {
			for(i = 0; i < cr->el_count; i++)
				asn1constraint_range_free(cr->elements[i]);
			free(cr->elements);
		}
        memset(cr, 0, sizeof(*cr));
    }
}
Esempio n. 2
0
int
asn1c_emit_constraint_checking_code(arg_t *arg) {
	asn1cnst_range_t *r_size;
	asn1cnst_range_t *r_value;
	asn1p_expr_t *expr = arg->expr;
	asn1p_expr_type_e etype;
	asn1p_constraint_t *ct;
	int got_something = 0;
	int alphabet_table_compiled;
	int produce_st = 0;
	int ulong_optimize = 0;

	ct = expr->combined_constraints;
	if(ct == NULL)
		return 1;	/* No additional constraints defined */

	etype = _find_terminal_type(arg);

	r_value=asn1constraint_compute_PER_range(etype, ct, ACT_EL_RANGE,0,0,0);
	r_size =asn1constraint_compute_PER_range(etype, ct, ACT_CT_SIZE, 0,0,0);
	if(r_value) {
		if(r_value->incompatible
		|| r_value->empty_constraint
		|| (r_value->left.type == ARE_MIN
			&& r_value->right.type == ARE_MAX)
		|| (etype == ASN_BASIC_BOOLEAN
			&& r_value->left.value == 0
			&& r_value->right.value == 1)
		) {
			asn1constraint_range_free(r_value);
			r_value = 0;
		}
	}
	if(r_size) {
		if(r_size->incompatible
		|| r_size->empty_constraint
		|| (r_size->left.value == 0	/* or .type == MIN */
			&& r_size->right.type == ARE_MAX)
		) {
			asn1constraint_range_free(r_size);
			r_size = 0;
		}
	}

	/*
	 * Do we really need an "*st = sptr" pointer?
	 */
	switch(etype) {
	case ASN_BASIC_INTEGER:
	case ASN_BASIC_ENUMERATED:
		if(asn1c_type_fits_long(arg, arg->expr) == FL_NOTFIT)
			produce_st = 1;
		break;
	case ASN_BASIC_REAL:
		if(!(arg->flags & A1C_USE_NATIVE_TYPES))
			produce_st = 1;
		break;
	case ASN_BASIC_BIT_STRING:
	case ASN_BASIC_OCTET_STRING:
		produce_st = 1;
		break;
	default:
		if(etype & ASN_STRING_MASK)
			produce_st = 1;
		break;
	}
	if(produce_st) {
		char *tname = asn1c_type_name(arg, arg->expr, TNF_SAFE);
		OUT("const %s_t *st = (const %s_t *)sptr;\n", tname, tname);
	}

	if(r_size || r_value) {
		if(r_size) {
			OUT("size_t size;\n");
		}
		if(r_value)
			switch(etype) {
			case ASN_BASIC_INTEGER:
			case ASN_BASIC_ENUMERATED:
				if(native_long_sign(r_value) >= 0) {
					ulong_optimize = ulong_optimization(etype, r_size, r_value);
					if(!ulong_optimize) {
						OUT("unsigned long value;\n");
					}
				} else {
					OUT("long value;\n");
				}
				break;
			case ASN_BASIC_REAL:
				OUT("double value;\n");
				break;
			case ASN_BASIC_BOOLEAN:
				OUT("BOOLEAN_t value;\n");
				break;
			default:
				break;
		}
	}

	OUT("\n");

	/*
	 * Protection against null input.
	 */
	OUT("if(!sptr) {\n");
		INDENT(+1);
		OUT("_ASN_CTFAIL(app_key, td, sptr,\n");
		OUT("\t\"%%s: value not given (%%s:%%d)\",\n");
		OUT("\ttd->name, __FILE__, __LINE__);\n");
		OUT("return -1;\n");
		INDENT(-1);
	OUT("}\n");
	OUT("\n");

	if((r_value) && (!ulong_optimize))
		emit_value_determination_code(arg, etype, r_value);
	if(r_size)
		emit_size_determination_code(arg, etype);

	INDENT(-1);
	REDIR(OT_CTABLES);
	/* Emit FROM() tables */
	alphabet_table_compiled =
		(asn1c_emit_constraint_tables(arg, r_size?1:0) == 1);
	REDIR(OT_CODE);
	INDENT(+1);

	/*
	 * Optimization for unsigned longs.
	 */
	if(ulong_optimize) {
		OUT("\n");
		OUT("/* Constraint check succeeded */\n");
		OUT("return 0;\n");
		return 0;
	}

	/*
	 * Here is an if() {} else {} consrtaint checking code.
	 */
	OUT("\n");
	OUT("if(");
	INDENT(+1);
		if(r_size) {
			if(got_something++) { OUT("\n"); OUT(" && "); }
			OUT("(");
			emit_range_comparison_code(arg, r_size, "size", 0, -1);
			OUT(")");
		}
		if(r_value) {
			if(got_something++) { OUT("\n"); OUT(" && "); }
			OUT("(");
			if(etype == ASN_BASIC_BOOLEAN)
				emit_range_comparison_code(arg, r_value,
					"value", 0, 1);
			else
				emit_range_comparison_code(arg, r_value,
					"value", -1, -1);
			OUT(")");
		}
		if(alphabet_table_compiled) {
			if(got_something++) { OUT("\n"); OUT(" && "); }
			OUT("!check_permitted_alphabet_%d(%s)",
				arg->expr->_type_unique_index,
				produce_st ? "st" : "sptr");
		}
		if(!got_something) {
			OUT("1 /* No applicable constraints whatsoever */");
			OUT(") {\n");
			INDENT(-1);
			INDENTED(OUT("/* Nothing is here. See below */\n"));
			OUT("}\n");
			OUT("\n");
			return 1;
		}
	INDENT(-1);
	OUT(") {\n");
		INDENT(+1);
		switch(etype) {
		case ASN_CONSTR_SEQUENCE_OF:
		case ASN_CONSTR_SET_OF:
			OUT("/* Perform validation of the inner elements */\n");
			OUT("return td->check_constraints(td, sptr, ctfailcb, app_key);\n");
			break;
		default:
			OUT("/* Constraint check succeeded */\n");
			OUT("return 0;\n");
		}
		INDENT(-1);
	OUT("} else {\n");
		INDENT(+1);
			OUT("_ASN_CTFAIL(app_key, td, sptr,\n");
			OUT("\t\"%%s: constraint failed (%%s:%%d)\",\n");
			OUT("\ttd->name, __FILE__, __LINE__);\n");
			OUT("return -1;\n");
		INDENT(-1);
	OUT("}\n");

	return 0;
}
Esempio n. 3
0
static int
asn1c_emit_constraint_tables(arg_t *arg, int got_size) {
	asn1c_integer_t range_start;
	asn1c_integer_t range_stop;
	asn1p_expr_type_e etype;
	asn1cnst_range_t *range;
	asn1p_constraint_t *ct;
	int utf8_full_alphabet_check = 0;
	int max_table_size = 256;
	int table[256];
	int use_table;

	ct = arg->expr->combined_constraints;
	if(!ct) return 0;

	etype = _find_terminal_type(arg);

	range = asn1constraint_compute_PER_range(etype, ct, ACT_CT_FROM, 0,0,0);
	if(!range) return 0;

	if(range->incompatible
	|| range->empty_constraint) {
		asn1constraint_range_free(range);
		return 0;
	}

	if(range->left.type == ARE_MIN
	&& range->right.type == ARE_MAX) {
		/*
		 * The permitted alphabet constraint checker code guarantees
		 * that either both bounds (left/right) are present, or
		 * they're absent simultaneously. Thus, this assertion
		 * legitimately holds true.
		 */
		assert(range->el_count == 0);
		/* The full range is specified. Ignore it. */
		return 0;
	}

	range_start = range->left.value;
	range_stop = range->right.value;
	assert(range->left.type == ARE_VALUE);
	assert(range->right.type == ARE_VALUE);
	assert(range_start <= range_stop);

	range_start = 0;	/* Force old behavior */

	/*
	 * Check if we need a test table to check the alphabet.
	 */
	use_table = 1;
	if(range->el_count == 0) {
		/*
		 * It's better to have a short if() check
		 * than waste 1k of table space
		 */
		use_table = 0;
	}
	if((range_stop - range_start) > 255)
		use_table = 0;
	if(etype == ASN_STRING_UTF8String) {
		if(range_stop >= 0x80)
			use_table = 0;
		else
			max_table_size = 128;
	}

	if(use_table) {
		int cardinal = 0;
		int i, n = 0;
		int untl;
		memset(table, 0, sizeof(table));
		for(i = -1; i < range->el_count; i++) {
			asn1cnst_range_t *r;
			asn1c_integer_t v;
			if(i == -1) {
				if(range->el_count) continue;
				r = range;
			} else {
				r = range->elements[i];
			}
			for(v = r->left.value; v <= r->right.value; v++) {
				assert((v - range_start) >= 0);
				assert((v - range_start) < max_table_size);
				table[v - range_start] = ++n;
			}
		}

		untl = (range_stop - range_start) + 1;
		untl += (untl % 16)?16 - (untl % 16):0;
		OUT("static int permitted_alphabet_table_%d[%d] = {\n",
			arg->expr->_type_unique_index, max_table_size);
		for(n = 0; n < untl; n++) {
			cardinal += table[n] ? 1 : 0;
			OUT("%2d,", table[n]);
			if(!((n+1) % 16)) {
				int c;
				if(!n || (n-15) + range_start >= 0x80) {
					OUT("\n");
					continue;
				}
				OUT("\t/* ");
				for(c = n - 15; c <= n; c++) {
					if(table[c]) {
						int a = c + range_start;
						if(a > 0x20 && a < 0x80)
							OUT("%c", a);
						else
							OUT(".");
					} else {
						OUT(" ");
					}
				}
				OUT(" */");
				OUT("\n");
			}
		}
		OUT("};\n");

		if((arg->flags & A1C_GEN_PER)
		&& (etype & ASN_STRING_KM_MASK)) {
		    int c;
		    OUT("static int permitted_alphabet_code2value_%d[%d] = {\n",
			arg->expr->_type_unique_index, cardinal);
		    for(n = c = 0; c < max_table_size; c++) {
			if(table[c]) {
				OUT("%d,", c);
				if(!((++n) % 16)) OUT("\n");
			}
		    }
		    OUT("};\n");
		    OUT("\n");
		    DEBUG("code2value map gen for %s", arg->expr->Identifier);
		    arg->expr->_mark |= TM_PERFROMCT;
		}

		OUT("\n");
	} else if(etype == ASN_STRING_UTF8String) {
		/*
		 * UTF8String type is a special case in many respects.
		 */
		if(got_size) {
			/*
			 * Size has been already determined.
			 * The UTF8String length checker also checks
			 * for the syntax validity, so we don't have
			 * to repeat this process twice.
			 */
			asn1constraint_range_free(range);
			return 0;
		} else {
			utf8_full_alphabet_check = 1;
		}
	} else {
		/*
		 * This permitted alphabet check will be
		 * expressed using conditional statements
		 * instead of table lookups. Table would be
		 * to large or otherwise inappropriate (too sparse?).
		 */
	}

	OUT("static int check_permitted_alphabet_%d(const void *sptr) {\n",
			arg->expr->_type_unique_index);
	INDENT(+1);
	if(utf8_full_alphabet_check) {
		OUT("if(UTF8String_length((const UTF8String_t *)sptr) < 0)\n");
		OUT("\treturn -1; /* Alphabet (sic!) test failed. */\n");
		OUT("\n");
	} else {
		if(use_table) {
			OUT("int *table = permitted_alphabet_table_%d;\n",
				arg->expr->_type_unique_index);
			emit_alphabet_check_loop(arg, 0);
		} else {
			emit_alphabet_check_loop(arg, range);
		}
	}
	OUT("return 0;\n");
	INDENT(-1);
	OUT("}\n");
	OUT("\n");

	asn1constraint_range_free(range);

	return 1;
}
Esempio n. 4
0
static asn1cnst_range_t *
asn1f_real_range_from_WCOMPS(const char *dbg_name,
                             const asn1p_constraint_t *ct) {
    asn1cnst_range_t two = {
        {ARE_VALUE, 0, 2}, {ARE_VALUE, 0, 2}, 0, NULL, 0, 0, 0, 0, 0, 0, 0};
    asn1cnst_range_t ten = {
        {ARE_VALUE, 0, 10}, {ARE_VALUE, 0, 10}, 0, NULL, 0, 0, 0, 0, 0, 0, 0};
    asn1cnst_range_t *two_ten[] = {&two, &ten};
    /* Interpretation of X.680 #21.5 */
    asn1cnst_range_t mantissa_default_range = {
        {ARE_MIN, 0, 0}, {ARE_MAX, 0, 0}, 0, NULL, 0, 0, 0, 0, 0, 0, 0};
    asn1cnst_range_t exponent_default_range = {
        {ARE_MIN, 0, 0}, {ARE_MAX, 0, 0}, 0, NULL, 0, 0, 0, 0, 0, 0, 0};
    asn1cnst_range_t base_default_range = {
        {ARE_VALUE, 0, 2}, {ARE_MAX, 0, 10}, 0, two_ten, 2, 0, 0, 0, 0, 0, 0};

    asn1cnst_range_t *mantissa = _range_clone(&mantissa_default_range);
    asn1cnst_range_t *exponent = _range_clone(&exponent_default_range);
    asn1cnst_range_t *base = _range_clone(&base_default_range);
    asn1cnst_range_t *range;

#define FREE_MEB()             \
    do {                       \
        _range_free(mantissa); \
        _range_free(exponent); \
        _range_free(base);     \
    } while(0)

    (void)dbg_name;

    assert(ct->type == ACT_CT_WCOMPS);

    range = _range_new();
    range->incompatible = 1;

    for(unsigned i = 0; i < ct->el_count; i++) {
        struct asn1p_constraint_s *el = ct->elements[i];
        asn1p_value_t *value = 0;
        asn1cnst_range_t **dst_range = 0;

        switch(el->type) {
        case ACT_EL_EXT:
            /* Some components might not be defined. */
            assert(range->incompatible);
            FREE_MEB();
            return range;
        default:
            assert(range->incompatible);
            FREE_MEB();
            return range;
        case ACT_EL_VALUE:
            value = el->value;
            if(value->type != ATV_REFERENCED) {
                FREE_MEB();
                return range;
            }
            break;
        }

        if(strcmp(asn1p_ref_string(value->value.reference), "mantissa") == 0) {
            dst_range = &mantissa;
        } else if(strcmp(asn1p_ref_string(value->value.reference), "exponent")
                  == 0) {
            dst_range = &exponent;
        } else if(strcmp(asn1p_ref_string(value->value.reference), "base")
                  == 0) {
            dst_range = &base;
        } else {
            FATAL("Invalid specification \"%s\" for REAL",
                  asn1p_ref_string(value->value.reference));
            FREE_MEB();
            return range;
        }

        switch(el->el_count) {
        case 0: continue;
        case 1: break;
        default:
            FATAL("Too many constraints (%u) for \"%s\" for REAL", el->el_count,
                  asn1p_ref_string(value->value.reference));
            FREE_MEB();
            return range;
        }

        asn1cnst_range_t *tmprange = asn1constraint_compute_constraint_range(
            dbg_name, ASN_BASIC_INTEGER, el->elements[0], ACT_EL_RANGE,
            *dst_range, 0, CPR_noflags);
        assert(tmprange);
        if(tmprange->incompatible) {
            _range_free(tmprange);
            FREE_MEB();
            return range;
        }
        asn1constraint_range_free(*dst_range);
        *dst_range = tmprange;
    }

    range->incompatible = 0;

    /* X.696 #12.2 */
    if(mantissa->left.type == ARE_VALUE && mantissa->right.type == ARE_VALUE
       && mantissa->left.value >= -16777215 && mantissa->right.value <= 16777215
       && base->left.type == ARE_VALUE && base->right.type == ARE_VALUE
       && base->left.value == 2 && base->right.value == 2
       && exponent->left.type == ARE_VALUE && exponent->right.type == ARE_VALUE
       && exponent->left.value >= -149 && exponent->right.value <= 104) {
        range->narrowing = NARROW_FLOAT32;
    } else /* X.696 #12.3 */
    if(mantissa->left.type == ARE_VALUE && mantissa->right.type == ARE_VALUE
       && mantissa->left.value >= -9007199254740991ll
       && mantissa->right.value <= 9007199254740991ull
       && base->left.type == ARE_VALUE && base->right.type == ARE_VALUE
       && base->left.value == 2 && base->right.value == 2
       && exponent->left.type == ARE_VALUE && exponent->right.type == ARE_VALUE
       && exponent->left.value >= -1074 && exponent->right.value <= 971) {
        range->narrowing = NARROW_DOUBLE64;
    }

    FREE_MEB();
    return range;
}