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(())
}

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