These expressions check whether array dimensions are not negative
upon creation. If negative size is detected then NegativeArraySizeException
is thrown.

Signed-off-by: Tomek Grabiec <[email protected]>
---
 arch/x86/insn-selector_32.brg         |   30 ++++++++++++++++++-
 include/jit/bc-offset-mapping.h       |    2 -
 include/jit/expression.h              |    7 ++++
 include/vm/class.h                    |    2 +
 jit/expression.c                      |   28 ++++++++++++++++++
 jit/object-bc.c                       |   22 +++++++++++--
 jit/tree-printer.c                    |   36 ++++++++++++++++++++++-
 test/arch-x86/insn-selector-test_32.c |   51 ---------------------------------
 test/jamvm/class-stub.c               |    9 ++++++
 test/jit/bc-test-utils.c              |   16 ++++++++++
 test/jit/bc-test-utils.h              |    3 +-
 test/jit/object-bc-test.c             |    9 ++---
 vm/class.c                            |   31 ++++++++++++++++++++
 13 files changed, 181 insertions(+), 65 deletions(-)

diff --git a/arch/x86/insn-selector_32.brg b/arch/x86/insn-selector_32.brg
index 7b9a933..12f7e9e 100644
--- a/arch/x86/insn-selector_32.brg
+++ b/arch/x86/insn-selector_32.brg
@@ -729,6 +729,18 @@ reg:       EXPR_NEW
        select_exception_test(s, tree);
 }
 
+reg:   EXPR_ARRAY_SIZE_CHECK(reg)
+{
+       struct var_info *size;
+
+       size = state->left->reg1;
+       state->reg1 = size;
+
+       select_insn(s, tree, reg_insn(INSN_PUSH_REG, size));
+       select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) 
array_size_check));
+       method_args_cleanup(s, tree, 1);
+}
+
 reg:   EXPR_NEWARRAY(reg)
 {
        struct var_info *var, *size;
@@ -778,12 +790,27 @@ reg:      EXPR_NULL_CHECK(EXPR_LOCAL)
        select_insn(s, tree, membase_reg_insn(INSN_TEST_MEMBASE_REG, reg, 0, 
reg));
 }
 
+arg:   EXPR_MULTIARRAY_SIZE_CHECK(arg)
+{
+       struct expression *expr;
+       int dimensions;
+
+       expr = to_expr(tree);
+       dimensions = nr_args(to_expr(expr->size_expr));
+
+       select_insn(s, tree, imm_insn(INSN_PUSH_IMM, dimensions));
+       select_insn(s, tree, rel_insn(INSN_CALL_REL,
+               (unsigned long) multiarray_size_check));
+       method_args_cleanup(s, tree, 1);
+}
+
 reg:   EXPR_MULTIANEWARRAY(arg)
 {
        struct var_info *var;
        struct var_info *stack_ptr;
        unsigned int dimension;
        struct expression *expr;
+       struct expression *size_check;
 
        expr = to_expr(tree);
 
@@ -792,7 +819,8 @@ reg:        EXPR_MULTIANEWARRAY(arg)
 
        stack_ptr = get_fixed_var(s->b_parent, REG_ESP);
 
-       dimension = nr_args(to_expr(expr->multianewarray_dimensions));
+       size_check = to_expr(expr->multianewarray_dimensions);
+       dimension = nr_args(to_expr(size_check->size_expr));
 
        select_insn(s, tree, reg_insn(INSN_PUSH_REG, stack_ptr));
        select_insn(s, tree, imm_insn(INSN_PUSH_IMM, dimension));
diff --git a/include/jit/bc-offset-mapping.h b/include/jit/bc-offset-mapping.h
index 21ec6df..c47ea51 100644
--- a/include/jit/bc-offset-mapping.h
+++ b/include/jit/bc-offset-mapping.h
@@ -11,8 +11,6 @@
 unsigned long native_ptr_to_bytecode_offset(struct compilation_unit *cu,
                                            unsigned char *native_ptr);
 void print_bytecode_offset(unsigned long bc_offset, struct string *str);
-
-unsigned long tree_bytecode_offset(struct tree_node *node);
 void tree_patch_bc_offset(struct tree_node *node, unsigned long bc_offset);
 bool all_insn_have_bytecode_offset(struct compilation_unit *cu);
 
diff --git a/include/jit/expression.h b/include/jit/expression.h
index 09943fd..43b41c0 100644
--- a/include/jit/expression.h
+++ b/include/jit/expression.h
@@ -33,6 +33,8 @@ enum expression_type {
        EXPR_INSTANCEOF,
        EXPR_EXCEPTION_REF,
        EXPR_NULL_CHECK,
+       EXPR_ARRAY_SIZE_CHECK,
+       EXPR_MULTIARRAY_SIZE_CHECK,
        EXPR_LAST,      /* Not a real type. Keep this last. */
 };
 
@@ -230,6 +232,9 @@ struct expression {
                /* EXPR_NULL_CHECK is used to assure that NullPointerException
                   will be thrown if reference is null. */
                struct tree_node *null_check_ref;
+
+               /* EXPR_ARRAY_SIZE_CHECK and EXPR_MULTIARRAY_SIZE_CHECK */
+               struct tree_node *size_expr;
        };
 };
 
@@ -282,6 +287,8 @@ struct expression *arraylength_expr(struct expression *);
 struct expression *instanceof_expr(struct expression *, struct object *);
 struct expression *exception_ref_expr(void);
 struct expression *null_check_expr(struct expression *);
+struct expression *array_size_check_expr(struct expression *);
+struct expression *multiarray_size_check_expr(struct expression *);
 
 unsigned long nr_args(struct expression *);
 int expr_nr_kids(struct expression *);
diff --git a/include/vm/class.h b/include/vm/class.h
index d78218b..6dd5b38 100644
--- a/include/vm/class.h
+++ b/include/vm/class.h
@@ -10,5 +10,7 @@ void check_array(struct object *obj, unsigned int index);
 void check_cast(struct object *obj, struct object *type);
 void array_store_check(struct object *arrayref, struct object *obj);
 void array_store_check_vmtype(struct object *arrayref, enum vm_type vm_type);
+void array_size_check(int size);
+void multiarray_size_check(int n, ...);
 
 #endif /* __CLASS_H */
diff --git a/jit/expression.c b/jit/expression.c
index 4905924..8e4d736 100644
--- a/jit/expression.c
+++ b/jit/expression.c
@@ -33,6 +33,8 @@ int expr_nr_kids(struct expression *expr)
        case EXPR_ARRAYLENGTH:
        case EXPR_INSTANCEOF:
        case EXPR_NULL_CHECK:
+       case EXPR_ARRAY_SIZE_CHECK:
+       case EXPR_MULTIARRAY_SIZE_CHECK:
                return 1;
        case EXPR_VALUE:
        case EXPR_FVALUE:
@@ -344,3 +346,29 @@ struct expression *null_check_expr(struct expression *ref)
 
        return expr;
 }
+
+struct expression *array_size_check_expr(struct expression *size)
+{
+       struct expression *expr;
+
+       expr = alloc_expression(EXPR_ARRAY_SIZE_CHECK, J_INT);
+       if (!expr)
+               return NULL;
+
+       expr->size_expr = &size->node;
+
+       return expr;
+}
+
+struct expression *multiarray_size_check_expr(struct expression *dimensions)
+{
+       struct expression *expr;
+
+       expr = alloc_expression(EXPR_MULTIARRAY_SIZE_CHECK, J_VOID);
+       if (!expr)
+               return NULL;
+
+       expr->size_expr = &dimensions->node;
+
+       return expr;
+}
diff --git a/jit/object-bc.c b/jit/object-bc.c
index a97a85f..5d39393 100644
--- a/jit/object-bc.c
+++ b/jit/object-bc.c
@@ -363,12 +363,17 @@ int convert_new(struct parse_context *ctx)
 int convert_newarray(struct parse_context *ctx)
 {
        struct expression *size, *arrayref;
+       struct expression *size_check;
        unsigned long type;
 
        size = stack_pop(ctx->bb->mimic_stack);
        type = bytecode_read_u8(ctx->buffer);
 
-       arrayref = newarray_expr(type, size);
+       size_check = array_size_check_expr(size);
+       if (!size_check)
+               return -ENOMEM;
+
+       arrayref = newarray_expr(type, size_check);
        if (!arrayref)
                return -ENOMEM;
 
@@ -379,6 +384,7 @@ int convert_newarray(struct parse_context *ctx)
 
 int convert_anewarray(struct parse_context *ctx)
 {
+       struct expression *size_check;
        struct expression *size,*arrayref;
        unsigned long type_idx;
        struct object *class, *arrayclass;
@@ -394,7 +400,11 @@ int convert_anewarray(struct parse_context *ctx)
        if (!arrayclass)
                return -EINVAL;
 
-       arrayref = anewarray_expr(arrayclass,size);
+       size_check = array_size_check_expr(size);
+       if (!size_check)
+               return -ENOMEM;
+
+       arrayref = anewarray_expr(arrayclass, size_check);
        if (!arrayref)
                return -ENOMEM;
 
@@ -405,6 +415,7 @@ int convert_anewarray(struct parse_context *ctx)
 
 int convert_multianewarray(struct parse_context *ctx)
 {
+       struct expression *size_check;
        struct expression *arrayref;
        struct expression *args_list;
        unsigned long type_idx;
@@ -423,10 +434,13 @@ int convert_multianewarray(struct parse_context *ctx)
                return -ENOMEM;
 
        args_list = convert_args(ctx->bb->mimic_stack, dimension);
-       arrayref->multianewarray_dimensions = &args_list->node;
-       if (!arrayref->multianewarray_dimensions)
+
+       size_check = multiarray_size_check_expr(args_list);
+       if (!size_check)
                return -ENOMEM;
 
+       arrayref->multianewarray_dimensions = &size_check->node;
+
        convert_expression(ctx, arrayref);
 
        return 0;
diff --git a/jit/tree-printer.c b/jit/tree-printer.c
index 49c113b..c96c87b 100644
--- a/jit/tree-printer.c
+++ b/jit/tree-printer.c
@@ -749,6 +749,37 @@ static int print_null_check_expr(int lvl, struct string 
*str,
        return err;
 }
 
+static int print_array_size_check_expr(int lvl, struct string *str,
+                                      struct expression *expr)
+{
+       int err;
+
+       err = append_formatted(lvl, str, "ARRAY_SIZE_CHECK:\n");
+       if (err)
+               goto out;
+
+       err = append_tree_attr(lvl + 1, str, "size", expr->size_expr);
+
+ out:
+       return err;
+}
+
+static int print_multiarray_size_check_expr(int lvl, struct string *str,
+                                           struct expression *expr)
+{
+       int err;
+
+       err = append_formatted(lvl, str, "MULTIARRAY_SIZE_CHECK:\n");
+       if (err)
+               goto out;
+
+       err = append_tree_attr(lvl + 1, str, "dimension list",
+                              expr->size_expr);
+
+ out:
+       return err;
+}
+
 typedef int (*print_expr_fn) (int, struct string * str, struct expression *);
 
 static print_expr_fn expr_printers[] = {
@@ -774,7 +805,10 @@ static print_expr_fn expr_printers[] = {
        [EXPR_ARRAYLENGTH] = print_arraylength_expr,
        [EXPR_INSTANCEOF] = print_instanceof_expr,
        [EXPR_EXCEPTION_REF] = print_exception_ref_expr,
-       [EXPR_NULL_CHECK] = print_null_check_expr
+       [EXPR_NULL_CHECK] = print_null_check_expr,
+       [EXPR_ARRAY_SIZE_CHECK] = print_array_size_check_expr,
+       [EXPR_MULTIARRAY_SIZE_CHECK] = print_multiarray_size_check_expr
+
 };
 
 static int print_expr(int lvl, struct tree_node *root, struct string *str)
diff --git a/test/arch-x86/insn-selector-test_32.c 
b/test/arch-x86/insn-selector-test_32.c
index 319b63a..5a9cdf4 100644
--- a/test/arch-x86/insn-selector-test_32.c
+++ b/test/arch-x86/insn-selector-test_32.c
@@ -1333,57 +1333,6 @@ void test_select_anewarray(void)
        free_compilation_unit(cu);
 }
 
-void test_select_multianewarray(void)
-{
-       struct object *instance_class;
-       struct compilation_unit *cu;
-       struct expression *expr, *args_list_expression;
-       struct statement *stmt;
-       struct basic_block *bb;
-       struct insn *insn;
-
-       instance_class = new_class();
-
-       args_list_expression = args_list_expr(arg_expr(value_expr(J_INT, 0x02)),
-                                             arg_expr(value_expr(J_INT, 
0xff)));
-
-       expr = multianewarray_expr(instance_class);
-       expr->multianewarray_dimensions = &args_list_expression->node;
-
-       stmt = alloc_statement(STMT_EXPRESSION);
-       stmt->expression = &expr->node;
-
-       cu = alloc_compilation_unit(&method);
-       bb = get_basic_block(cu, 0, 1);
-       bb_add_stmt(bb, stmt);
-
-       select_instructions(bb->b_parent);
-
-       insn = list_first_entry(&bb->insn_list, struct insn, insn_list_node);
-       assert_imm_insn(INSN_PUSH_IMM, 0x02, insn);
-
-       insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_imm_insn(INSN_PUSH_IMM, 0xff, insn);
-
-       insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_reg_insn(INSN_PUSH_REG, REG_ESP, insn);
-
-       insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_imm_insn(INSN_PUSH_IMM, 0x02, insn);
-
-       insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_imm_insn(INSN_PUSH_IMM, (unsigned long) instance_class, insn);
-
-       insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_rel_insn(INSN_CALL_REL, (unsigned long) allocMultiArray, insn);
-
-       insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_imm_reg_insn(INSN_ADD_IMM_REG, 20, REG_ESP, insn);
-
-       free(instance_class);
-       free_compilation_unit(cu);
-}
-
 void test_select_arraylength(void)
 {
        struct object *instance_class;
diff --git a/test/jamvm/class-stub.c b/test/jamvm/class-stub.c
index 0ef5576..83aac13 100644
--- a/test/jamvm/class-stub.c
+++ b/test/jamvm/class-stub.c
@@ -42,3 +42,12 @@ void array_store_check(struct object *arrayref, struct 
object *obj)
 void array_store_check_vmtype(struct object *arrayref, enum vm_type vm_type)
 {
 }
+
+void array_size_check(int size)
+{
+}
+
+void multiarray_size_check(int n, ...)
+{
+}
+
diff --git a/test/jit/bc-test-utils.c b/test/jit/bc-test-utils.c
index 54375f3..c4e973e 100644
--- a/test/jit/bc-test-utils.c
+++ b/test/jit/bc-test-utils.c
@@ -5,6 +5,7 @@
 #include <jit/compilation-unit.h>
 #include <jit/basic-block.h>
 #include <bc-test-utils.h>
+#include <args-test-utils.h>
 #include <jit/tree-node.h>
 #include <jit/expression.h>
 #include <jit/statement.h>
@@ -210,6 +211,21 @@ void assert_invoke_expr(enum vm_type expected_type,
        assert_ptr_equals(expected_method, expr->target_method);
 }
 
+void assert_array_size_check_expr(struct expression *expected,
+                                 struct expression *actual)
+{
+       assert_int_equals(EXPR_ARRAY_SIZE_CHECK, expr_type(actual));
+       assert_ptr_equals(&expected->node, actual->size_expr);
+}
+
+void assert_multiarray_size_check_expr(struct expression **expected_args,
+                                      int nr_args,
+                                      struct expression *actual)
+{
+       assert_int_equals(EXPR_MULTIARRAY_SIZE_CHECK, expr_type(actual));
+       assert_args(expected_args, nr_args, to_expr(actual->size_expr));
+}
+
 void assert_store_stmt(struct statement *stmt)
 {
        assert_int_equals(STMT_STORE, stmt_type(stmt));
diff --git a/test/jit/bc-test-utils.h b/test/jit/bc-test-utils.h
index 76324cc..514b09a 100644
--- a/test/jit/bc-test-utils.h
+++ b/test/jit/bc-test-utils.h
@@ -36,7 +36,8 @@ void assert_class_field_expr(enum vm_type, struct fieldblock 
*, struct tree_node
 void assert_instance_field_expr(enum vm_type, struct fieldblock *, struct 
expression *, struct tree_node *);
 void assert_invoke_expr(enum vm_type, struct methodblock *,
                        struct tree_node *);
-
+void assert_array_size_check_expr(struct expression *, struct expression *);
+void assert_multiarray_size_check_expr(struct expression **, int, struct 
expression *);
 void assert_store_stmt(struct statement *);
 void assert_array_store_check_stmt(struct statement *, struct expression *, 
struct tree_node *);
 void assert_return_stmt(struct expression *, struct statement *);
diff --git a/test/jit/object-bc-test.c b/test/jit/object-bc-test.c
index d5c8976..ad04680 100644
--- a/test/jit/object-bc-test.c
+++ b/test/jit/object-bc-test.c
@@ -455,7 +455,7 @@ void test_convert_anewarray(void)
 
        assert_int_equals(EXPR_ANEWARRAY, expr_type(arrayref));
        assert_int_equals(J_REFERENCE, arrayref->vm_type);
-       assert_ptr_equals(size, to_expr(arrayref->anewarray_size));
+       assert_array_size_check_expr(size, to_expr(arrayref->anewarray_size));
 
         /*
         * Free the struct object returned from findArrayClassFromClassLoader()
@@ -488,7 +488,7 @@ void test_convert_newarray(void)
        arrayref = stack_pop(bb->mimic_stack);
        assert_int_equals(EXPR_NEWARRAY, expr_type(arrayref));
        assert_int_equals(J_REFERENCE, arrayref->vm_type);
-       assert_ptr_equals(size, to_expr(arrayref->array_size));
+       assert_array_size_check_expr(size, to_expr(arrayref->array_size));
        assert_int_equals(T_INT, arrayref->array_type);
 
        expr_put(arrayref);
@@ -502,7 +502,6 @@ void test_convert_multianewarray(void)
        unsigned char code[] = { OPC_MULTIANEWARRAY, 0x00, 0x00, dimension };
        struct expression *arrayref;
        struct expression *args_count[dimension];
-       struct expression *actual_args;
        struct basic_block *bb;
        struct methodblock method = {
                .jit_code = code,
@@ -522,8 +521,8 @@ void test_convert_multianewarray(void)
        assert_int_equals(J_REFERENCE, arrayref->vm_type);
        assert_ptr_equals(instance_class, arrayref->multianewarray_ref_type);
 
-       actual_args = to_expr(arrayref->multianewarray_dimensions);
-       assert_args(args_count, dimension, actual_args);
+       assert_multiarray_size_check_expr(args_count, dimension,
+               to_expr(arrayref->multianewarray_dimensions));
 
        assert_true(stack_is_empty(bb->mimic_stack));
 
diff --git a/vm/class.c b/vm/class.c
index 3748f75..d8d1fc9 100644
--- a/vm/class.c
+++ b/vm/class.c
@@ -197,3 +197,34 @@ void check_cast(struct object *obj, struct object *type)
 
        die("%s: error %d", __func__, err);
 }
+
+void array_size_check(int size)
+{
+       if (size < 0) {
+               signal_new_exception(
+                       "java/lang/NegativeArraySizeException", NULL);
+               throw_from_native(sizeof(int));
+       }
+}
+
+void multiarray_size_check(int n, ...)
+{
+       va_list ap;
+       int i;
+
+       va_start(ap, n);
+
+       for (i = 0; i < n; i++) {
+               if (va_arg(ap, int) >= 0)
+                       continue;
+
+               signal_new_exception("java/lang/NegativeArraySizeException",
+                                    NULL);
+               va_end(ap);
+               throw_from_native(sizeof(int) * (n + 1));
+               return;
+       }
+
+       va_end(ap);
+       return;
+}
-- 
1.6.0.6


------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing 
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
Jatovm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to