From fb29955f7d2a63fe5d832fa63483970e68472e2d Mon Sep 17 00:00:00 2001 From: VegOwOtenks Date: Mon, 2 Sep 2024 12:02:19 +0200 Subject: [PATCH] More error checking in invokestatic --- src/accessmasks.rs | 9 +++++++++ src/classstore.rs | 5 +++++ src/jvm.rs | 29 +++++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/accessmasks.rs b/src/accessmasks.rs index 33b7dbf..398fbdc 100644 --- a/src/accessmasks.rs +++ b/src/accessmasks.rs @@ -1,4 +1,5 @@ use core::fmt::{Formatter, Debug}; +use core::ops::BitAnd; #[derive(Debug, Copy, Clone)] #[repr(u16)] @@ -36,10 +37,18 @@ impl MethodAccessFlag { } } +#[derive(Copy, Clone)] pub struct MethodAccessFlagMask { pub mask: u16, } +impl BitAnd for MethodAccessFlagMask { + type Output=bool; + fn bitand(self, f: MethodAccessFlag) -> bool { + return (self.mask & f.discriminant()) != 0; + } +} + impl Debug for MethodAccessFlagMask { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { let mut flag_vec = Vec::new(); diff --git a/src/classstore.rs b/src/classstore.rs index 715302b..93df77f 100644 --- a/src/classstore.rs +++ b/src/classstore.rs @@ -130,6 +130,11 @@ impl ClassStore { return Some(was_init); } + + pub fn set_init(&mut self, class_idx: usize, was_init: bool) { + let pair = self.classes.get_mut(class_idx).unwrap(); + pair.0 = was_init; + } } diff --git a/src/jvm.rs b/src/jvm.rs index 385bb26..0b46519 100644 --- a/src/jvm.rs +++ b/src/jvm.rs @@ -17,6 +17,7 @@ pub enum Error { ClassFileError(classfile::Error), BadNameError(String), RunTimeError(String), + OpcodeError(String), } impl From for Error { @@ -151,6 +152,7 @@ impl JVM { // TODO: ConstantValue Attributes (final) // TODO: Static Stuff + self.class_store.set_init(class_idx, true); } fn prepare_invoke_static(&mut self, class_index: usize, method_name: &String, arguments: &[Value]) -> Result<(), Error> { @@ -210,6 +212,17 @@ impl JVM { // TODO: Throw exception on fail let callee_method_info = &callee_class_file.methods[callee_method_index]; + if ! (callee_method_info.access_flags & MethodAccessFlag::Static) { + // TODO: Throw IncompatibleClassChangeError + return Err(Error::RunTimeError(format!( + "Invoked method '{}' in class '{}' does not have Access::Static (from invokestatic from '{}' in class '{}')", + method.name, + class.get_classname().unwrap(), + supplied_method_name, + supplied_class_name, + ))); + } + let supplied_descriptor: MethodDescriptor = supplied_descriptor_string.try_into()?; // TODO: Throw exception on fail @@ -225,6 +238,7 @@ impl JVM { } let arguments = Vec::new(); + // TODO: Pass arguments let new_frame = StackFrame::new( callee_class_file, @@ -233,11 +247,22 @@ impl JVM { &arguments.into_boxed_slice(), ); - //println!("{} {} {}", class_name, method_name, method_descriptor); - return Ok(JVMCallbackOperation::PushFrame(new_frame)); }, + Instruction::ReturnVoid() => { + let expected_type = AbstractTypeDescription { + array_level: 0, + kind: AbstractTypeKind::Void(), + }; + + if method.descriptor.return_type != expected_type { + return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type))) + } + + return Ok(JVMCallbackOperation::PopFrame()); + }, + _ => { return Err(Error::RunTimeError(format!("Opcode not implemented yet: {:?}", instruction))) },