⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asn1c_constraint.c

📁 RSA加密/解密算法源码 asn1c-0.9.12
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "asn1c_internal.h"#include "asn1c_constraint.h"#include "asn1c_misc.h"#include "asn1c_out.h"#include <asn1fix_crange.h>	/* constraint groker from libasn1fix */#include <asn1fix_export.h>	/* other exportable stuff from libasn1fix */static int asn1c_emit_constraint_tables(arg_t *arg, int got_size);static int emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range);static int emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype, asn1cnst_range_t *r_value);static int emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype);static asn1p_expr_type_e _find_terminal_type(arg_t *arg);static int emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1c_integer_t natural_start, asn1c_integer_t natural_stop);intasn1c_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;	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:	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:				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_ERRLOG(app_errlog, app_key,\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)		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);	/*	 * Here is an if() {} else {} constaint 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);		OUT("/* Constraint check succeeded */\n");		OUT("return 0;\n");		INDENT(-1);	OUT("} else {\n");		INDENT(+1);			OUT("_ASN_ERRLOG(app_errlog, app_key,\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;}static intasn1c_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 4k 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 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++) {			OUT("%d,", table[n]?1:0);			if(!((n+1) % 16)) {				int c;				if(!n) {					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");		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.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -