asn1c_constraint.c

来自「RSA加密/解密算法源码 asn1c-0.9.12」· C语言 代码 · 共 630 行 · 第 1/2 页

C
630
字号
			 */			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;}static intemit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range) {	asn1c_integer_t natural_stop;	asn1p_expr_t *terminal;	char *tname;	terminal = asn1f_find_terminal_type_ex(arg->asn, arg->expr);	if(terminal) {		OUT("/* The underlying type is %s */\n",			ASN_EXPR_TYPE2STR(terminal->expr_type));	} else {		terminal = arg->expr;	}	tname = asn1c_type_name(arg, terminal, TNF_SAFE);	OUT("const %s_t *st = (const %s_t *)sptr;\n", tname, tname);	switch(terminal->expr_type) {	case ASN_STRING_UTF8String:		OUT("const uint8_t *ch = st->buf;\n");		OUT("const uint8_t *end = ch + st->size;\n");		OUT("\n");		OUT("for(; ch < end; ch++) {\n");			INDENT(+1);			OUT("uint8_t cv = *ch;\n");			if(!range) OUT("if(cv >= 0x80) return -1;\n");		natural_stop = 0xffffffffUL;		break;	case ASN_STRING_UniversalString:		OUT("const uint8_t *ch = st->buf;\n");		OUT("const uint8_t *end = ch + st->size;\n");		OUT("\n");		OUT("if(st->size %% 4) return -1; /* (size%%4)! */\n");		OUT("for(; ch < end; ch += 4) {\n");			INDENT(+1);			OUT("uint32_t cv = (ch[0] << 24)\n");			OUT("\t\t| (ch[1] << 16)\n");			OUT("\t\t| (ch[2] << 8)\n");			OUT("\t\t|  ch[3];\n");			if(!range) OUT("if(cv > 255) return -1;\n");		natural_stop = 0xffffffffUL;		break;	case ASN_STRING_BMPString:		OUT("const uint8_t *ch = st->buf;\n");		OUT("const uint8_t *end = ch + st->size;\n");		OUT("\n");		OUT("if(st->size %% 2) return -1; /* (size%%2)! */\n");		OUT("for(; ch < end; ch += 2) {\n");			INDENT(+1);			OUT("uint16_t cv = (ch[0] << 8)\n");			OUT("\t\t| ch[1];\n");			if(!range) OUT("if(cv > 255) return -1;\n");		natural_stop = 0xffff;		break;	case ASN_BASIC_OCTET_STRING:	default:		OUT("const uint8_t *ch = st->buf;\n");		OUT("const uint8_t *end = ch + st->size;\n");		OUT("\n");		OUT("for(; ch < end; ch++) {\n");			INDENT(+1);			OUT("uint8_t cv = *ch;\n");		natural_stop = 0xff;		break;	}	if(range) {		OUT("if(!(");		emit_range_comparison_code(arg, range, "cv", 0, natural_stop);		OUT(")) return -1;\n");	} else {		OUT("if(!table[cv]) return -1;\n");	}	INDENT(-1);	OUT("}\n");	return 0;}static intemit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1c_integer_t natural_start, asn1c_integer_t natural_stop) {	int ignore_left;	int ignore_right;	int generated_something = 0;	int i;	for(i = -1; i < range->el_count; i++) {		asn1cnst_range_t *r;		if(i == -1) {			if(range->el_count) continue;			r = range;		} else {			if(i) OUT(" || ");			r = range->elements[i];		}		if(r != range) OUT("(");		ignore_left = (r->left.type == ARE_MIN)				|| (natural_start != -1					&& r->left.value <= natural_start);		ignore_right = (r->right.type == ARE_MAX)				|| (natural_stop != -1					&& r->right.value >= natural_stop);		if(ignore_left && ignore_right) {			OUT("1 /* Constraint matches natural range of %s */",				varname);			continue;		}		if(ignore_left) {			OUT("%s <= %" PRIdASN, varname,				r->right.value);		} else if(ignore_right) {			OUT("%s >= %" PRIdASN, varname,				r->left.value);		} else if(r->left.value == r->right.value) {			OUT("%s == %" PRIdASN, varname,				r->right.value);		} else {			OUT("%s >= %" PRIdASN " && %s <= %" PRIdASN,				varname,				r->left.value,				varname,				r->right.value);		}		if(r != range) OUT(")");		generated_something = 1;	}	return generated_something;}static intemit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype) {	switch(etype) {	case ASN_BASIC_BIT_STRING:		OUT("if(st->size > 0) {\n");		OUT("\t/* Size in bits */\n");		OUT("\tsize = 8 * (st->size - 1) - (st->buf[0] & 0x7);\n");		OUT("} else {\n");		OUT("\tsize = 0;\n");		OUT("}\n");		break;	case ASN_STRING_UniversalString:		OUT("size = st->size >> 2;\t/* 4 byte per character */\n");		break;	case ASN_STRING_BMPString:		OUT("size = st->size >> 1;\t/* 2 byte per character */\n");		break;	case ASN_STRING_UTF8String:		OUT("size = UTF8String_length(st);\n");		OUT("if((ssize_t)size < 0) {\n");		OUT("\t_ASN_ERRLOG(app_errlog, app_key,\n");		OUT("\t\t\"%%s: UTF-8: broken encoding (%%s:%%d)\",\n");		OUT("\t\ttd->name, __FILE__, __LINE__);\n");		OUT("\treturn -1;\n");		OUT("}\n");		break;	case ASN_CONSTR_SET_OF:	case ASN_CONSTR_SEQUENCE_OF:		OUT("{ /* Determine the number of elements */\n");			INDENT(+1);			OUT("const A_%s_OF(void) *list;\n",				etype==ASN_CONSTR_SET_OF?"SET":"SEQUENCE");			OUT("(const void *)list = sptr;\n");			OUT("size = list->count;\n");			INDENT(-1);		OUT("}\n");		break;	case ASN_BASIC_OCTET_STRING:		OUT("size = st->size;\n");		break;	default:		if(etype & ASN_STRING_MASK) {			OUT("size = st->size;\n");			break;		} else {			const char *type_name = ASN_EXPR_TYPE2STR(etype);			if(!type_name) type_name = arg->expr->Identifier;			WARNING("SizeConstraint is not defined for %s",				type_name);			OUT_NOINDENT("#warning SizeConstraint "				"is not defined for %s!\n", type_name);			OUT("size = st->size;\n");		}		return -1;	}	return 0;}static intemit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype, asn1cnst_range_t *r_value) {	switch(etype) {	case ASN_BASIC_INTEGER:	case ASN_BASIC_ENUMERATED:		if(arg->flags & A1C_USE_NATIVE_TYPES) {			OUT("value = *(const long *)sptr;\n");		} else {			if(r_value->el_count == 0			&& (				/* Speed-up common case: (0..MAX) */				(r_value->left.type == ARE_VALUE				&& r_value->left.value == 0				&& r_value->right.type == ARE_MAX)			    ||				/* Speed-up common case: (MIN..-1) */				(r_value->left.type == ARE_MIN				&& r_value->right.type == ARE_VALUE				&& r_value->right.value == -1)			)) {				OUT("/* Check if the sign bit is present */\n");				OUT("value = st->buf ? ((st->buf[0] & 0x80) ? -1 : 1) : 0;\n");				break;			}			OUT("if(asn_INTEGER2long(st, &value)) {\n");				INDENT(+1);				OUT("_ASN_ERRLOG(app_errlog, app_key,\n");				OUT("\t\"%%s: value too large (%%s:%%d)\",\n");				OUT("\ttd->name, __FILE__, __LINE__);\n");				OUT("return -1;\n");				INDENT(-1);			OUT("}\n");		}		break;	case ASN_BASIC_REAL:		if(arg->flags & A1C_USE_NATIVE_TYPES) {			OUT("value = *(const double *)sptr;\n");		} else {			OUT("if(asn_REAL2double(st, &value)) {\n");				INDENT(+1);				OUT("_ASN_ERRLOG(app_errlog, app_key,\n");				OUT("\t\"%%s: value too large (%%s:%%d)\",\n");				OUT("\ttd->name, __FILE__, __LINE__);\n");				OUT("return -1;\n");				INDENT(-1);			OUT("}\n");		}		break;	case ASN_BASIC_BOOLEAN:		OUT("value = (*(const long *)sptr) ? 1 : 0;\n");		break;	default:		WARNING("%s:%d: Value cannot be determined "			"for constraint check for %s",			arg->mod->source_file_name,			arg->expr->_lineno,			arg->expr->Identifier		);		OUT_NOINDENT(			"#error %s:%d: Value of %s cannot be determined\n",			arg->mod->source_file_name,			arg->expr->_lineno,			arg->expr->Identifier		);		break;	}	return 0;}static asn1p_expr_type_e_find_terminal_type(arg_t *arg) {	asn1p_expr_t *expr;	expr = asn1f_find_terminal_type_ex(arg->asn, arg->expr);	if(expr) return expr->expr_type;	return A1TC_INVALID;}

⌨️ 快捷键说明

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