📄 pvmjac.c
字号:
#include <jpr/utf8.h>#include <aegisvm/pvm.h>#include "jac.h"//#define JAC_PVM_DEBUGintjac_pvm_init(void) { return 0;}intjac_pvm_finish(void) { return 0;}const void *jac_find_jac_attribute(const PREClassFile *classfile) { const PREConstantPool *constant_pool; const void *attr; const void *the_attr = 0; constant_pool = pre_classfile_constant_pool(classfile); for (attr = pre_classfile_attributes(classfile); attr != 0; attr = pre_attribute_next(attr)) { if (pre_attribute_type(attr) != PRE_ATTR_Generic) continue; ju2 attribute_name_index = pre_attribute_attribute_name_index(attr); const char *attribute_name = pre_constant_pool_utf8_bytes(constant_pool, attribute_name_index); if (! j_utf8_eq(attribute_name, "JAC")) continue; if (the_attr != 0) return 0; the_attr = attr; } return the_attr;}static inlinebooljac_valid_type_annotation(char c) { return c == 'R' || c == '.';}static inlinebooljac_valid_primitive_type_annotation(char c) { return c == '.';}booljac_validate_field_annotation(const PREConstantPool *constant_pool, ju2 descriptor_index, ju2 annotation_index) { /* Check if annotation_index refers to a valid utf8 cp entry */ if (!pre_cp_index_is_valid(constant_pool, annotation_index, J_CONSTANT_Utf8)) return false; /* Fetch descriptor and annotation string */ const char *descriptor = pre_constant_pool_utf8_bytes(constant_pool, descriptor_index); const char *annotation = pre_constant_pool_utf8_bytes(constant_pool, annotation_index); /* Annotation should consist of one character only */ if (j_strlen(annotation) != 1) return false; /* Annotation should be consistent with descriptor */ switch (*descriptor) { case J_ASCII_reference: case J_ASCII_array: return jac_valid_type_annotation(*annotation); default: return jac_valid_primitive_type_annotation(*annotation); }}booljac_validate_method_annotation(const PREConstantPool *constant_pool, ju2 descriptor_index, ju2 annotation_index, bool known_to_be_static) { /* Check if annotation_index refers to a valid utf8 cp entry */ if (!pre_cp_index_is_valid(constant_pool, annotation_index, J_CONSTANT_Utf8)) return false; /* Fetch descriptor and annotation string */ const char *descriptor = pre_constant_pool_utf8_bytes(constant_pool, descriptor_index); const char *annotation = pre_constant_pool_utf8_bytes(constant_pool, annotation_index); /* Annotation for 'this' */ if (known_to_be_static) { if (! jac_valid_primitive_type_annotation(*annotation)) return false; } else { if (! jac_valid_type_annotation(*annotation)) return false; } ++annotation; /* Skip over left bracket */ if (*annotation != J_ASCII_lbracket) return false; ++annotation; ++descriptor; /* Annotations for argument list */ while (*descriptor != J_ASCII_rbracket) { switch (*descriptor) { case J_ASCII_boolean: case J_ASCII_byte: case J_ASCII_char: case J_ASCII_short: case J_ASCII_int: case J_ASCII_float: if (! jac_valid_primitive_type_annotation(*annotation)) return false; ++annotation; ++descriptor; break; case J_ASCII_long: case J_ASCII_double: if (! jac_valid_primitive_type_annotation(*annotation)) return false; ++annotation; if (! jac_valid_primitive_type_annotation(*annotation)) return false; ++annotation; ++descriptor; break; case J_ASCII_reference: if (! jac_valid_type_annotation(*annotation)) return false; ++annotation; do { ++descriptor; } while (*descriptor != J_ASCII_terminator); ++descriptor; break; case J_ASCII_array: if (! jac_valid_type_annotation(*annotation)) return false; ++annotation; do { ++descriptor; } while (*descriptor == J_ASCII_array); switch (*descriptor) { case J_ASCII_boolean: case J_ASCII_byte: case J_ASCII_char: case J_ASCII_short: case J_ASCII_int: case J_ASCII_float: case J_ASCII_long: case J_ASCII_double: ++descriptor; break; case J_ASCII_reference: do { ++descriptor; } while (*descriptor != J_ASCII_terminator); ++descriptor; break; default: j_assert_not_reached(); } break; default: j_assert_not_reached(); } } /* Skip over right bracket */ if (*annotation != J_ASCII_rbracket) return false; ++annotation; ++descriptor; /* Annotation for return type */ switch (*descriptor) { case J_ASCII_reference: case J_ASCII_array: if (! jac_valid_type_annotation(*annotation)) return false; break; default: if (! jac_valid_primitive_type_annotation(*annotation)) return false; break; } ++annotation; /* Annotation should terminate at this point */ if (*annotation != '\0') return false; /* Annotation is properly validated */ return true;}booljac_parse_constant_annotations(JArena *arena, const void **begin, const PREClassFile *classfile, ju2 constant_annotations_count, ju2 **result) { /* Allocate memory for annotations */ ju2 constant_pool_count = pre_classfile_constant_pool_count(classfile); ju2 *annotations = j_arena_alloc_array(arena, constant_pool_count, sizeof(ju2)); if (annotations == 0) return false; /* Initialize annotation array to zero */ j_memset(annotations, 0, constant_pool_count * sizeof(ju2)); /* Parsing loop */ ju2 i, last; const PREConstantPool *constant_pool = pre_classfile_constant_pool(classfile); for (i = 0; i < constant_annotations_count; i++) { /* Read id and index */ ju2 id = j_parse_u2(begin); ju2 index = j_parse_u2(begin); /* Validate id */ if (i != 0) { if (id <= last) return false; /* constant id must be strictly increasing */ } else { last = id; } if (! pre_cp_index_is_in_range(constant_pool, id)) return false; /* Validate index */ const void *cp = pre_constant_pool_entry(constant_pool, id); ju1 tag = pre_cp_tag(cp); ju2 descriptor_index; switch (tag) { case J_CONSTANT_Fieldref: descriptor_index = pre_constant_pool_fieldref_descriptor_index(constant_pool, id); if (! jac_validate_field_annotation(constant_pool, descriptor_index, index)) return false; break; case J_CONSTANT_Methodref: descriptor_index = pre_constant_pool_methodref_descriptor_index(constant_pool, id); if (! jac_validate_method_annotation(constant_pool, descriptor_index, index, false)) return false; break; case J_CONSTANT_InterfaceMethodref: descriptor_index = pre_constant_pool_interface_methodref_descriptor_index(constant_pool, id); if (! jac_validate_method_annotation(constant_pool, descriptor_index, index, false)) return false; break; default: return false; } /* Install annotation */ annotations[id] = index; } /* Return result */ *result = annotations; return true;}booljac_parse_field_annotations(JArena *arena, const void **begin, const PREClassFile *classfile, ju2 field_annotations_count, ju2 **result) { /* Allocate memory for annotations */ ju2 fields_count = pre_classfile_fields_count(classfile); ju2 *annotations = j_arena_alloc_array(arena, fields_count, sizeof(ju2)); if (annotations == 0) return false; /* Initialize annotation array to zero */ j_memset(annotations, 0, fields_count * sizeof(ju2)); /* Parsing loop */ ju2 i, last; const PREConstantPool *constant_pool = pre_classfile_constant_pool(classfile); for (i = 0; i < field_annotations_count; i++) { /* Read id and index */ ju2 id = j_parse_u2(begin); ju2 index = j_parse_u2(begin); /* Validate id */ if (i != 0) { if (id <= last) return false; /* field id must be strictly increasing */ } else { last = id; } if (id >= fields_count) return false; /* Validate index */ ju2 descriptor_index = pre_classfile_field_descriptor_index(classfile, id); if (! jac_validate_field_annotation(constant_pool, descriptor_index, index)) return false; /* Install annotation */ annotations[id] = index; } /* Return result */ *result = annotations; return true;}booljac_parse_method_annotations(JArena *arena, const void **begin, const PREClassFile *classfile, ju2 method_annotations_count, ju2 **result) { /* Allocate memory for annotations */ ju2 methods_count = pre_classfile_methods_count(classfile); ju2 *annotations = j_arena_alloc_array(arena, methods_count, sizeof(ju2)); if (annotations == 0) return false; /* Initialize annotation array to zero */ j_memset(annotations, 0, methods_count * sizeof(ju2)); /* Parsing loop */ ju2 i, last; const PREConstantPool *constant_pool = pre_classfile_constant_pool(classfile); for (i = 0; i < method_annotations_count; i++) { /* Read id and index */ ju2 id = j_parse_u2(begin); ju2 index = j_parse_u2(begin); /* Validate id */ if (i != 0) { if (id <= last) /* method id must be strictly increasing */ return false; } else { last = id; } if (id >= methods_count) return false; /* Validate index */ ju2 descriptor_index = pre_classfile_method_descriptor_index(classfile, id); bool known_to_be_static = pre_method_is_static(pre_classfile_method(classfile, id)); if (! jac_validate_method_annotation(constant_pool, descriptor_index, index, known_to_be_static)) return false; /* Install annotation */ annotations[id] = index; } /* Return result */ *result = annotations; return true;}static inlineconst char *jac_get_constant_annotation(const struct jac_commitments *commitments, const PREConstantPool *constant_pool, ju2 cp_index) { ju2 index = jac_get_constant_annotation_index(commitments, cp_index); if (index != 0) return pre_constant_pool_utf8_bytes(constant_pool, index); else return 0;}static inlineconst char *jac_get_field_annotation(const struct jac_commitments *commitments, const PREConstantPool *constant_pool, ju2 field_index) { ju2 index = jac_get_method_annotation_index(commitments, field_index); if (index != 0) return pre_constant_pool_utf8_bytes(constant_pool, index); else return 0;}static inlineconst char *jac_get_method_annotation(const struct jac_commitments *commitments, const PREConstantPool *constant_pool, ju2 method_index) { ju2 index = jac_get_method_annotation_index(commitments, method_index); if (index != 0) return pre_constant_pool_utf8_bytes(constant_pool, index); else return 0;}booljac_parse_jac_attribute(JArena *arena, const PREClassFile *classfile, const void *attr, struct jac_commitments **result) { const void *check_point = j_arena_check_point(arena); ju4 attribute_length = pre_attribute_attribute_length(attr); const void *begin = pre_attribute_generic_info(attr); const void *end = begin + attribute_length; /* Enough bytes left in input? */ if (end - begin < sizeof(ju2) * 4) goto ErrorExit; /* Read header */ ju2 class_annotation_index = j_parse_u2(&begin); ju2 constant_annotations_count = j_parse_u2(&begin); ju2 field_annotations_count = j_parse_u2(&begin); ju2 method_annotations_count = j_parse_u2(&begin); /* Validate class_annotation_index */ if (class_annotation_index != 0) goto ErrorExit; /* Enough bytes left in input? */ if (end - begin < constant_annotations_count * (sizeof(ju2) + sizeof(ju2)) + field_annotations_count * (sizeof(ju2) + sizeof(ju2)) + method_annotations_count * (sizeof(ju2) + sizeof(ju2))) goto ErrorExit; /* Parse constant annotations */ ju2 *constant_annotations; if (! jac_parse_constant_annotations(arena, &begin, classfile, constant_annotations_count, &constant_annotations)) goto ErrorExit; /* Parse field annotations */ ju2 *field_annotations; if (! jac_parse_field_annotations(arena, &begin, classfile, field_annotations_count, &field_annotations)) goto ErrorExit; /* Parse method annotations */ ju2 *method_annotations; if (! jac_parse_method_annotations(arena, &begin, classfile, method_annotations_count, &method_annotations)) goto ErrorExit; j_assert(begin == end); /* Refrain from allocating memory if no annotation is found */ if (constant_annotations == 0 && field_annotations == 0 && method_annotations == 0) { *result = 0; return true; } /* Allocate memory for commitment structure */ struct jac_commitments *commitments = j_arena_alloc(arena, sizeof(struct jac_commitments)); if (commitments == 0) goto ErrorExit; /* Install annotations into commitment structure */ commitments->class_annotation = 0; commitments->constant_annotations = constant_annotations; commitments->field_annotations = field_annotations; commitments->method_annotations = method_annotations; /* Return result */ *result = commitments; return true; ErrorExit: j_arena_free(arena, check_point); return false;}static inlinebooljac_meet(char *des, const char *src, bool *updated) { if (jac_subtype(*src, *des)) return true; if (*src == JAC_TYP_ReadOnly) return false; *des = *src; *updated = true; return true;}typedef struct JACState JACState;struct JACState { ju2 max_locals; ju2 max_stack; char *locals; char *stack; char *top;};JACState *jac_allocate_state(JArena *arena, ju2 max_locals, ju2 max_stack) { const void *check_point = j_arena_check_point(arena); JACState *state = j_arena_alloc(arena, sizeof(JACState)); if (state == 0) goto ErrorExit; state->locals = j_arena_alloc(arena, max_locals); if (state->locals == 0) goto ErrorExit; state->stack = j_arena_alloc(arena, max_stack); if (state->stack == 0) goto ErrorExit; state->max_locals = max_locals; state->max_stack = max_stack; return state; ErrorExit: j_arena_free(arena, check_point); return 0;}voidjac_copy_state(JACState *des, const JACState *src) { j_memcpy(des->locals, src->locals, src->max_locals); j_memcpy(des->stack, src->stack, src->max_stack); des->top = des->stack + (src->top - src->stack);}voidjac_initialize_first_state(const PREAnalysis *analysis, const struct jac_commitments *commitments, JACState *state) { const PREClassFile *classfile = pre_analysis_classfile(analysis); const PREConstantPool *constant_pool = pre_classfile_constant_pool(classfile); ju2 method_index = pre_analysis_method_index(analysis); const PREMethod *method = pre_classfile_method(classfile, method_index);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -