diff options
author | Pekka Enberg <penberg@kernel.org> | 2012-04-26 17:25:04 +0300 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2013-03-24 13:11:47 +0200 |
commit | 170fd5059fe1e089521e74d59ca606cda136a037 (patch) | |
tree | 84076d1823d63cabe7fc65047a758b71ebab2eb8 | |
parent | 6d8cef69dac21b1f0db22e84e03ba2ebb6c1c115 (diff) | |
download | jato-170fd5059fe1e089521e74d59ca606cda136a037.tar.gz |
jit: Verify method argument types
Reported-by: Vegard Nossum <vegard.nossum@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r-- | jit/bytecode-to-ir.c | 7 | ||||
-rw-r--r-- | jit/invoke-bc.c | 83 |
2 files changed, 83 insertions, 7 deletions
diff --git a/jit/bytecode-to-ir.c b/jit/bytecode-to-ir.c index ce27f68f..c055c0dd 100644 --- a/jit/bytecode-to-ir.c +++ b/jit/bytecode-to-ir.c @@ -185,8 +185,11 @@ int convert_instruction(struct parse_context *ctx) ctx->cu->flags |= CU_FLAG_ARRAY_OPC; err = convert(ctx); - if (err) - warn("conversion error at PC=%lu", ctx->offset); + if (err) { + struct vm_method *vmm = ctx->cu->method; + + warn("%s.%s%s: conversion error at PC=%lu", vmm->class->name, vmm->name, vmm->type, ctx->offset); + } return err; } diff --git a/jit/invoke-bc.c b/jit/invoke-bc.c index 6c829baa..6701a7ca 100644 --- a/jit/invoke-bc.c +++ b/jit/invoke-bc.c @@ -1,20 +1,39 @@ /* - * Copyright (C) 2005-2006 Pekka Enberg + * Method invocation bytecode parsing + * Copyright (c) 2005-2012 Pekka Enberg * - * This file is released under the GPL version 2. Please refer to the file - * LICENSE for details. + * This file is released under the GPL version 2 with the following + * clarification and special exception: * - * The file contains functions for converting Java bytecode method invocation - * and return instructions to immediate representation of the JIT compiler. + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under terms + * of your choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. An + * independent module is a module which is not derived from or based on + * this library. If you modify this library, you may extend this exception + * to your version of the library, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + * Please refer to the file LICENSE for details. */ #include "jit/bytecode-to-ir.h" +#include "jit/exception.h" #include "jit/statement.h" #include "jit/compiler.h" #include "jit/args.h" #include "vm/bytecode.h" +#include "vm/preload.h" #include "vm/method.h" #include "vm/class.h" #include "vm/die.h" @@ -53,6 +72,57 @@ int convert_return(struct parse_context *ctx) return 0; } +static enum vm_type vm_method_arg_type(struct vm_method_arg *arg) +{ + switch (arg->type_info.vm_type) { + case J_BOOLEAN: + case J_SHORT: + case J_BYTE: + case J_CHAR: + return J_INT; + default: + break; + } + return arg->type_info.vm_type; +} + +static bool verify_arg_types(struct vm_method *vmm, struct expression **args_array, unsigned long nr_args) +{ + struct vm_method_arg *arg; + unsigned long idx = 0; + + list_for_each_entry_reverse(arg, &vmm->args, list_node) { + struct expression *expr = args_array[idx]; + enum vm_type type = vm_method_arg_type(arg); + + if (expr->vm_type != type) { + signal_new_exception(vm_java_lang_VerifyError, + "(class: %s, method: %s, signature :%s): Expecting to find %d on stack (was %d).", + vmm->class->name, vmm->name, vmm->type, idx, type, expr->vm_type); + return false; + } + + if (vm_type_is_pair(expr->vm_type)) + idx++; + + if (idx++ >= nr_args) + break; + } + + return true; +} + +static unsigned int method_real_argument_count(struct vm_method *invoke_target) +{ + int argc; + + argc = vm_method_arg_slots(invoke_target); + if (!vm_method_is_static(invoke_target)) + argc++; + + return argc; +} + static int convert_and_add_args(struct parse_context *ctx, struct vm_method *invoke_target, struct statement *stmt) @@ -80,6 +150,9 @@ static int convert_and_add_args(struct parse_context *ctx, break; } + if (!verify_arg_types(invoke_target, args_array, nr_args)) + return -EINVAL; + args_list = convert_args(args_array, nr_args, invoke_target); if (!args_list) { free(args_array); |