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 + -
显示快捷键?