Skip to content

failed to read a classfile with MethodParameters #3

Description

@manlge
use std::{error::Error, fs::File, io::Cursor};

use jvmti::bytecode::{ClassReader, ClassWriter};

fn main() -> Result<(), Box<dyn Error>> {
    let path = "XXX.class";
    let class_file = ClassReader::read_class(&mut File::open(path).unwrap()).unwrap();

    let mut data = Vec::new();

    let mut w: ClassWriter = ClassWriter::new(&mut data);
    w.write_class(&class_file).unwrap();

    let mut reader = Cursor::new(data);
    ClassReader::read_class(&mut reader).unwrap();
    Ok(())
}
called `Result::unwrap()` on an `Err` value: Error { kind: UnexpectedEof, message: "failed to fill whole buffer" }
stack backtrace:
   0: rust_begin_unwind
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/std/src/panicking.rs:645:5
   1: core::panicking::panic_fmt
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/panicking.rs:72:14
   2: core::result::unwrap_failed
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/result.rs:1653:5
   3: core::result::Result<T,E>::unwrap
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/result.rs:1077:23
   4: yms_launcher1::main
             at ./examples/yms-launcher1.rs:15:5
   5: core::ops::function::FnOnce::call_once
             at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

MethodParameters read codes
"MethodParameters" => Some(Attribute::MethodParameters({
let n = reader.get_u8();
(0..n).map(|_| MethodParameter {
name_index: ConstantPoolIndex::new(reader.get_u16() as usize),
access_flags: AccessFlags::of(reader.get_u16())
}).collect()
})),

MethodParameters write codes:
&Attribute::MethodParameters(ref table) => self
.write_u16(cp.get_utf8_index("MethodParameters") as u16)
.and(self.write_u32(1 + table.len() as u32 * 4))
.and(table.iter().fold(Ok(0), |_, p| {
self.write_u16(p.name_index.idx as u16)
.and(self.write_u16(p.access_flags.flags as u16))
})),

I modified it like this and still got an error
self.write_u8(table.len() as u8)

Remove all MethodParameters, code runs just fine.

use std::{error::Error, fs::File, io::Cursor};
use jvmti::bytecode::{Attribute, ClassReader, ClassWriter};
fn main() -> Result<(), Box<dyn Error>> {
    let path = "XXX.class";
    let mut class_file = ClassReader::read_class(&mut File::open(path).unwrap()).unwrap();

    //remove all MethodParameters
    for method in &mut class_file.methods {
        method.attributes.retain(|a| match a {
            Attribute::MethodParameters(_) => false,
            _ => true,
        });
    }

    let mut data = Vec::new();
    let mut w: ClassWriter = ClassWriter::new(&mut data);
    w.write_class(&class_file).unwrap();

    let mut reader = Cursor::new(data);
    ClassReader::read_class(&mut reader).unwrap();
    Ok(())
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions