1use crate::constant_pool::CpInfo;
2use crate::error::ClassReadError;
3use crate::insn::{
4 AbstractInsnNode, FieldInsnNode, IincInsnNode, Insn, InsnList, InsnNode, IntInsnNode,
5 InvokeDynamicInsnNode, InvokeInterfaceInsnNode, JumpInsnNode, LabelNode, LdcInsnNode, LdcValue,
6 LookupSwitchInsnNode, MemberRef, MethodInsnNode, MultiANewArrayInsnNode, TableSwitchInsnNode,
7 TryCatchBlockNode, TypeInsnNode, VarInsnNode,
8};
9use crate::types::Type;
10use crate::{constants, opcodes};
11
12#[derive(Debug, Clone)]
17pub enum LdcConstant {
18 Integer(i32),
20 Float(f32),
22 Long(i64),
24 Double(f64),
26 String(String),
28 Class(String),
30 MethodType(String),
32 MethodHandle {
34 reference_kind: u8,
35 reference_index: u16,
36 },
37 Dynamic,
39}
40
41pub trait FieldVisitor {
46 fn visit_end(&mut self) {}
51}
52
53pub trait MethodVisitor {
54 fn visit_code(&mut self) {}
56
57 fn visit_insn(&mut self, _opcode: u8) {}
62
63 fn visit_int_insn(&mut self, _opcode: u8, _operand: i32) {}
65
66 fn visit_var_insn(&mut self, _opcode: u8, _var_index: u16) {}
68
69 fn visit_type_insn(&mut self, _opcode: u8, _type_name: &str) {}
75
76 fn visit_field_insn(&mut self, _opcode: u8, _owner: &str, _name: &str, _desc: &str) {}
84 fn visit_method_insn(
85 &mut self,
86 _opcode: u8,
87 _owner: &str,
88 _name: &str,
89 _desc: &str,
90 _is_interface: bool,
91 ) {
92 }
93 fn visit_invoke_dynamic_insn(&mut self, _name: &str, _desc: &str) {}
94 fn visit_jump_insn(&mut self, _opcode: u8, _target_offset: i32) {}
100
101 fn visit_ldc_insn(&mut self, _value: LdcConstant) {}
103 fn visit_iinc_insn(&mut self, _var_index: u16, _increment: i16) {}
104 fn visit_table_switch(&mut self, _default: i32, _low: i32, _high: i32, _targets: &[i32]) {}
105 fn visit_lookup_switch(&mut self, _default: i32, _pairs: &[(i32, i32)]) {}
106 fn visit_multi_anewarray_insn(&mut self, _type_name: &str, _dims: u8) {}
107 fn visit_maxs(&mut self, _max_stack: u16, _max_locals: u16) {}
108 fn visit_end(&mut self) {}
109}
110
111pub trait ClassVisitor {
116 fn visit(
127 &mut self,
128 _major: u16,
129 _minor: u16,
130 _access_flags: u16,
131 _name: &str,
132 _super_name: Option<&str>,
133 _interfaces: &[String],
134 ) {
135 }
136
137 fn visit_source(&mut self, _source: &str) {}
139
140 fn visit_field(
144 &mut self,
145 _access_flags: u16,
146 _name: &str,
147 _descriptor: &str,
148 ) -> Option<Box<dyn FieldVisitor>> {
149 None
150 }
151
152 fn visit_method(
156 &mut self,
157 _access_flags: u16,
158 _name: &str,
159 _descriptor: &str,
160 ) -> Option<Box<dyn MethodVisitor>> {
161 None
162 }
163
164 fn visit_end(&mut self) {}
166}
167
168pub struct ClassReader {
174 bytes: Vec<u8>,
175}
176
177impl ClassReader {
178 pub fn new(bytes: &[u8]) -> Self {
184 Self {
185 bytes: bytes.to_vec(),
186 }
187 }
188
189 pub fn accept(
202 &self,
203 visitor: &mut dyn ClassVisitor,
204 _options: u32,
205 ) -> Result<(), ClassReadError> {
206 let class_file = read_class_file(&self.bytes)?;
207 let name = class_file.class_name(class_file.this_class)?.to_string();
208 let super_name = if class_file.super_class == 0 {
209 None
210 } else {
211 Some(class_file.class_name(class_file.super_class)?.to_string())
212 };
213 let mut interfaces = Vec::with_capacity(class_file.interfaces.len());
214 for index in &class_file.interfaces {
215 interfaces.push(class_file.class_name(*index)?.to_string());
216 }
217
218 visitor.visit(
219 class_file.major_version,
220 class_file.minor_version,
221 class_file.access_flags,
222 &name,
223 super_name.as_deref(),
224 &interfaces,
225 );
226
227 for attr in &class_file.attributes {
228 if let AttributeInfo::SourceFile { sourcefile_index } = attr {
229 let source = class_file.cp_utf8(*sourcefile_index)?;
230 visitor.visit_source(source);
231 }
232 }
233
234 for field in &class_file.fields {
235 let field_name = class_file.cp_utf8(field.name_index)?;
236 let field_desc = class_file.cp_utf8(field.descriptor_index)?;
237 if let Some(mut fv) = visitor.visit_field(field.access_flags, field_name, field_desc) {
238 fv.visit_end();
239 }
240 }
241
242 for method in &class_file.methods {
243 let method_name = class_file.cp_utf8(method.name_index)?;
244 let method_desc = class_file.cp_utf8(method.descriptor_index)?;
245 if let Some(mut mv) =
246 visitor.visit_method(method.access_flags, method_name, method_desc)
247 {
248 let code = method.attributes.iter().find_map(|attr| match attr {
249 AttributeInfo::Code(code) => Some(code),
250 _ => None,
251 });
252 if let Some(code) = code {
253 mv.visit_code();
254 let instructions = parse_code_instructions_with_offsets(&code.code)?;
255 for instruction in instructions {
256 visit_instruction(
257 &class_file.constant_pool,
258 instruction.offset as i32,
259 instruction.insn,
260 &mut *mv,
261 )?;
262 }
263 mv.visit_maxs(code.max_stack, code.max_locals);
264 }
265 mv.visit_end();
266 }
267 }
268
269 visitor.visit_end();
270 Ok(())
271 }
272
273 pub fn to_class_node(&self) -> Result<crate::nodes::ClassNode, ClassReadError> {
278 let class_file = read_class_file(&self.bytes)?;
279 class_file.to_class_node()
280 }
281}
282
283#[derive(Debug, Clone)]
284pub struct ClassFile {
285 pub minor_version: u16,
286 pub major_version: u16,
287 pub constant_pool: Vec<CpInfo>,
288 pub access_flags: u16,
289 pub this_class: u16,
290 pub super_class: u16,
291 pub interfaces: Vec<u16>,
292 pub fields: Vec<FieldInfo>,
293 pub methods: Vec<MethodInfo>,
294 pub attributes: Vec<AttributeInfo>,
295}
296
297impl ClassFile {
298 pub fn cp_utf8(&self, index: u16) -> Result<&str, ClassReadError> {
299 match self
300 .constant_pool
301 .get(index as usize)
302 .ok_or(ClassReadError::InvalidIndex(index))?
303 {
304 CpInfo::Utf8(value) => Ok(value.as_str()),
305 _ => Err(ClassReadError::InvalidIndex(index)),
306 }
307 }
308
309 pub fn class_name(&self, index: u16) -> Result<&str, ClassReadError> {
310 match self
311 .constant_pool
312 .get(index as usize)
313 .ok_or(ClassReadError::InvalidIndex(index))?
314 {
315 CpInfo::Class { name_index } => self.cp_utf8(*name_index),
316 _ => Err(ClassReadError::InvalidIndex(index)),
317 }
318 }
319
320 pub fn to_class_node(&self) -> Result<crate::nodes::ClassNode, ClassReadError> {
321 let name = self.class_name(self.this_class)?.to_string();
322 let super_name = if self.super_class == 0 {
323 None
324 } else {
325 Some(self.class_name(self.super_class)?.to_string())
326 };
327 let source_file = self.attributes.iter().find_map(|attr| match attr {
328 AttributeInfo::SourceFile { sourcefile_index } => self
329 .cp_utf8(*sourcefile_index)
330 .ok()
331 .map(|value| value.to_string()),
332 _ => None,
333 });
334 let mut interfaces = Vec::with_capacity(self.interfaces.len());
335 for index in &self.interfaces {
336 interfaces.push(self.class_name(*index)?.to_string());
337 }
338
339 let mut fields = Vec::with_capacity(self.fields.len());
340 for field in &self.fields {
341 let name = self.cp_utf8(field.name_index)?.to_string();
342 let descriptor = self.cp_utf8(field.descriptor_index)?.to_string();
343 fields.push(crate::nodes::FieldNode {
344 access_flags: field.access_flags,
345 name,
346 descriptor,
347 attributes: field.attributes.clone(),
348 });
349 }
350
351 let mut methods = Vec::with_capacity(self.methods.len());
352 for method in &self.methods {
353 let name = self.cp_utf8(method.name_index)?.to_string();
354 let descriptor = self.cp_utf8(method.descriptor_index)?.to_string();
355 let mut method_attributes = method.attributes.clone();
356 method_attributes.retain(|attr| !matches!(attr, AttributeInfo::Code(_)));
357 let code = method.attributes.iter().find_map(|attr| match attr {
358 AttributeInfo::Code(code) => Some(code),
359 _ => None,
360 });
361
362 let (has_code, max_stack, max_locals, instructions, exception_table, code_attributes) =
363 if let Some(code) = code {
364 let mut list = InsnList::new();
365 for insn in &code.instructions {
366 list.add(insn.clone());
367 }
368 (
369 true,
370 code.max_stack,
371 code.max_locals,
372 list,
373 code.exception_table.clone(),
374 code.attributes.clone(),
375 )
376 } else {
377 (false, 0, 0, InsnList::new(), Vec::new(), Vec::new())
378 };
379
380 methods.push(crate::nodes::MethodNode {
381 access_flags: method.access_flags,
382 name,
383 descriptor,
384 has_code,
385 max_stack,
386 max_locals,
387 instructions,
388 exception_table,
389 code_attributes,
390 attributes: method_attributes,
391 });
392 }
393
394 let mut inner_classes = Vec::new();
395 for attr in &self.attributes {
396 if let AttributeInfo::InnerClasses { classes } = attr {
397 for entry in classes {
398 let name = self.class_name(entry.inner_class_info_index)?.to_string();
399 let outer_name = if entry.outer_class_info_index == 0 {
400 None
401 } else {
402 Some(self.class_name(entry.outer_class_info_index)?.to_string())
403 };
404 let inner_name = if entry.inner_name_index == 0 {
405 None
406 } else {
407 Some(self.cp_utf8(entry.inner_name_index)?.to_string())
408 };
409 inner_classes.push(crate::nodes::InnerClassNode {
410 name,
411 outer_name,
412 inner_name,
413 access_flags: entry.inner_class_access_flags,
414 });
415 }
416 }
417 }
418
419 let mut outer_class = String::new();
420 if let Some(class_index) = self.attributes.iter().find_map(|attr| match attr {
421 AttributeInfo::EnclosingMethod { class_index, .. } => Some(*class_index),
422 _ => None,
423 }) {
424 outer_class = self.class_name(class_index)?.to_string();
425 }
426 if outer_class.is_empty() {
427 for attr in &self.attributes {
428 if let AttributeInfo::InnerClasses { classes } = attr
429 && let Some(entry) = classes.iter().find(|entry| {
430 entry.inner_class_info_index == self.this_class
431 && entry.outer_class_info_index != 0
432 })
433 {
434 outer_class = self.class_name(entry.outer_class_info_index)?.to_string();
435 break;
436 }
437 }
438 }
439
440 Ok(crate::nodes::ClassNode {
441 minor_version: self.minor_version,
442 major_version: self.major_version,
443 access_flags: self.access_flags,
444 constant_pool: self.constant_pool.clone(),
445 this_class: self.this_class,
446 name,
447 super_name,
448 source_file,
449 interfaces,
450 interface_indices: self.interfaces.clone(),
451 fields,
452 methods,
453 attributes: self.attributes.clone(),
454 inner_classes,
455 outer_class,
456 })
457 }
458}
459
460#[derive(Debug, Clone)]
461pub struct FieldInfo {
462 pub access_flags: u16,
463 pub name_index: u16,
464 pub descriptor_index: u16,
465 pub attributes: Vec<AttributeInfo>,
466}
467
468#[derive(Debug, Clone)]
469pub struct MethodInfo {
470 pub access_flags: u16,
471 pub name_index: u16,
472 pub descriptor_index: u16,
473 pub attributes: Vec<AttributeInfo>,
474}
475
476#[derive(Debug, Clone)]
477pub enum AttributeInfo {
478 Code(CodeAttribute),
479 ConstantValue { constantvalue_index: u16 },
480 Exceptions { exception_index_table: Vec<u16> },
481 SourceFile { sourcefile_index: u16 },
482 LineNumberTable { entries: Vec<LineNumber> },
483 LocalVariableTable { entries: Vec<LocalVariable> },
484 Signature { signature_index: u16 },
485 StackMapTable { entries: Vec<StackMapFrame> },
486 Deprecated,
487 Synthetic,
488 InnerClasses { classes: Vec<InnerClass> },
489 EnclosingMethod { class_index: u16, method_index: u16 },
490 BootstrapMethods { methods: Vec<BootstrapMethod> },
491 MethodParameters { parameters: Vec<MethodParameter> },
492 RuntimeVisibleAnnotations { annotations: Vec<Annotation> },
493 RuntimeInvisibleAnnotations { annotations: Vec<Annotation> },
494 RuntimeVisibleParameterAnnotations { parameters: ParameterAnnotations },
495 RuntimeInvisibleParameterAnnotations { parameters: ParameterAnnotations },
496 RuntimeVisibleTypeAnnotations { annotations: Vec<TypeAnnotation> },
497 RuntimeInvisibleTypeAnnotations { annotations: Vec<TypeAnnotation> },
498 Unknown { name: String, info: Vec<u8> },
499}
500
501#[derive(Debug, Clone, PartialEq)]
502pub struct Annotation {
503 pub type_descriptor_index: u16,
504 pub element_value_pairs: Vec<ElementValuePair>,
505}
506
507#[derive(Debug, Clone, PartialEq)]
508pub struct ElementValuePair {
509 pub element_name_index: u16,
510 pub value: ElementValue,
511}
512
513#[derive(Debug, Clone, PartialEq)]
514pub enum ElementValue {
515 ConstValueIndex {
516 tag: u8,
517 const_value_index: u16,
518 },
519 EnumConstValue {
520 type_name_index: u16,
521 const_name_index: u16,
522 },
523 ClassInfoIndex {
524 class_info_index: u16,
525 },
526 AnnotationValue(Box<Annotation>),
527 ArrayValue(Vec<ElementValue>),
528}
529
530#[derive(Debug, Clone, PartialEq)]
531pub struct ParameterAnnotations {
532 pub parameters: Vec<Vec<Annotation>>,
533}
534
535#[derive(Debug, Clone, PartialEq)]
536pub struct TypeAnnotation {
537 pub target_type: u8,
538 pub target_info: TypeAnnotationTargetInfo,
539 pub target_path: TypePath,
540 pub annotation: Annotation,
541}
542
543#[derive(Debug, Clone, PartialEq)]
544pub struct TypePath {
545 pub path: Vec<TypePathEntry>,
546}
547
548#[derive(Debug, Clone, PartialEq)]
549pub struct TypePathEntry {
550 pub type_path_kind: u8,
551 pub type_argument_index: u8,
552}
553
554#[derive(Debug, Clone, PartialEq)]
555pub enum TypeAnnotationTargetInfo {
556 TypeParameter {
557 type_parameter_index: u8,
558 },
559 Supertype {
560 supertype_index: u16,
561 },
562 TypeParameterBound {
563 type_parameter_index: u8,
564 bound_index: u8,
565 },
566 Empty,
567 FormalParameter {
568 formal_parameter_index: u8,
569 },
570 Throws {
571 throws_type_index: u16,
572 },
573 LocalVar {
574 table: Vec<LocalVarTargetTableEntry>,
575 },
576 Catch {
577 exception_table_index: u16,
578 },
579 Offset {
580 offset: u16,
581 },
582 TypeArgument {
583 offset: u16,
584 type_argument_index: u8,
585 },
586}
587
588#[derive(Debug, Clone, PartialEq)]
589pub struct LocalVarTargetTableEntry {
590 pub start_pc: u16,
591 pub length: u16,
592 pub index: u16,
593}
594
595#[derive(Debug, Clone)]
596pub struct CodeAttribute {
597 pub max_stack: u16,
598 pub max_locals: u16,
599 pub code: Vec<u8>,
600 pub instructions: Vec<Insn>,
601 pub insn_nodes: Vec<AbstractInsnNode>,
602 pub exception_table: Vec<ExceptionTableEntry>,
603 pub try_catch_blocks: Vec<TryCatchBlockNode>,
604 pub attributes: Vec<AttributeInfo>,
605}
606
607#[derive(Debug, Clone)]
608pub struct ExceptionTableEntry {
609 pub start_pc: u16,
610 pub end_pc: u16,
611 pub handler_pc: u16,
612 pub catch_type: u16,
613}
614
615#[derive(Debug, Clone)]
616pub struct LineNumber {
617 pub start_pc: u16,
618 pub line_number: u16,
619}
620
621#[derive(Debug, Clone)]
622pub struct LocalVariable {
623 pub start_pc: u16,
624 pub length: u16,
625 pub name_index: u16,
626 pub descriptor_index: u16,
627 pub index: u16,
628}
629
630#[derive(Debug, Clone)]
631pub struct InnerClass {
632 pub inner_class_info_index: u16,
633 pub outer_class_info_index: u16,
634 pub inner_name_index: u16,
635 pub inner_class_access_flags: u16,
636}
637
638#[derive(Debug, Clone)]
639pub struct BootstrapMethod {
640 pub bootstrap_method_ref: u16,
641 pub bootstrap_arguments: Vec<u16>,
642}
643
644#[derive(Debug, Clone)]
645pub struct MethodParameter {
646 pub name_index: u16,
647 pub access_flags: u16,
648}
649
650#[derive(Debug, Clone, PartialEq, Eq)]
651pub enum VerificationTypeInfo {
652 Top,
653 Integer,
654 Float,
655 Long,
656 Double,
657 Null,
658 UninitializedThis,
659 Object { cpool_index: u16 },
660 Uninitialized { offset: u16 },
661}
662
663#[derive(Debug, Clone)]
664pub enum StackMapFrame {
665 SameFrame {
666 offset_delta: u16,
667 },
668 SameLocals1StackItemFrame {
669 offset_delta: u16,
670 stack: VerificationTypeInfo,
671 },
672 SameLocals1StackItemFrameExtended {
673 offset_delta: u16,
674 stack: VerificationTypeInfo,
675 },
676 ChopFrame {
677 offset_delta: u16,
678 k: u8,
679 },
680 SameFrameExtended {
681 offset_delta: u16,
682 },
683 AppendFrame {
684 offset_delta: u16,
685 locals: Vec<VerificationTypeInfo>,
686 },
687 FullFrame {
688 offset_delta: u16,
689 locals: Vec<VerificationTypeInfo>,
690 stack: Vec<VerificationTypeInfo>,
691 },
692}
693
694pub fn read_class_file(bytes: &[u8]) -> Result<ClassFile, ClassReadError> {
695 let mut reader = ByteReader::new(bytes);
696 let magic = reader.read_u4()?;
697 if magic != 0xCAFEBABE {
698 return Err(ClassReadError::InvalidMagic(magic));
699 }
700 let minor_version = reader.read_u2()?;
701 let major_version = reader.read_u2()?;
702 if major_version > constants::V25 {
703 return Err(ClassReadError::InvalidClassVersion(major_version));
704 }
705 let constant_pool = read_constant_pool(&mut reader)?;
706 let access_flags = reader.read_u2()?;
707 let this_class = reader.read_u2()?;
708 let super_class = reader.read_u2()?;
709 let interfaces = read_u2_table(&mut reader)?;
710 let fields = read_fields(&mut reader, &constant_pool)?;
711 let methods = read_methods(&mut reader, &constant_pool)?;
712 let attributes = read_attributes(&mut reader, &constant_pool)?;
713
714 Ok(ClassFile {
715 minor_version,
716 major_version,
717 constant_pool,
718 access_flags,
719 this_class,
720 super_class,
721 interfaces,
722 fields,
723 methods,
724 attributes,
725 })
726}
727
728fn read_constant_pool(reader: &mut ByteReader<'_>) -> Result<Vec<CpInfo>, ClassReadError> {
729 let count = reader.read_u2()? as usize;
730 let mut pool = Vec::with_capacity(count);
731 pool.push(CpInfo::Unusable);
732
733 let mut index = 1;
734 while index < count {
735 let tag = reader.read_u1()?;
736 let entry = match tag {
737 1 => {
738 let len = reader.read_u2()? as usize;
739 let bytes = reader.read_bytes(len)?;
740 let value = decode_modified_utf8(&bytes)?;
741 CpInfo::Utf8(value)
742 }
743 3 => {
744 let value = reader.read_u4()? as i32;
745 CpInfo::Integer(value)
746 }
747 4 => {
748 let value = f32::from_bits(reader.read_u4()?);
749 CpInfo::Float(value)
750 }
751 5 => {
752 let value = reader.read_u8()? as i64;
753 CpInfo::Long(value)
754 }
755 6 => {
756 let value = f64::from_bits(reader.read_u8()?);
757 CpInfo::Double(value)
758 }
759 7 => CpInfo::Class {
760 name_index: reader.read_u2()?,
761 },
762 8 => CpInfo::String {
763 string_index: reader.read_u2()?,
764 },
765 9 => CpInfo::Fieldref {
766 class_index: reader.read_u2()?,
767 name_and_type_index: reader.read_u2()?,
768 },
769 10 => CpInfo::Methodref {
770 class_index: reader.read_u2()?,
771 name_and_type_index: reader.read_u2()?,
772 },
773 11 => CpInfo::InterfaceMethodref {
774 class_index: reader.read_u2()?,
775 name_and_type_index: reader.read_u2()?,
776 },
777 12 => CpInfo::NameAndType {
778 name_index: reader.read_u2()?,
779 descriptor_index: reader.read_u2()?,
780 },
781 15 => CpInfo::MethodHandle {
782 reference_kind: reader.read_u1()?,
783 reference_index: reader.read_u2()?,
784 },
785 16 => CpInfo::MethodType {
786 descriptor_index: reader.read_u2()?,
787 },
788 17 => CpInfo::Dynamic {
789 bootstrap_method_attr_index: reader.read_u2()?,
790 name_and_type_index: reader.read_u2()?,
791 },
792 18 => CpInfo::InvokeDynamic {
793 bootstrap_method_attr_index: reader.read_u2()?,
794 name_and_type_index: reader.read_u2()?,
795 },
796 19 => CpInfo::Module {
797 name_index: reader.read_u2()?,
798 },
799 20 => CpInfo::Package {
800 name_index: reader.read_u2()?,
801 },
802 _ => return Err(ClassReadError::InvalidConstantPoolTag(tag)),
803 };
804
805 pool.push(entry);
806
807 if tag == 5 || tag == 6 {
808 pool.push(CpInfo::Unusable);
809 index += 2;
810 } else {
811 index += 1;
812 }
813 }
814
815 Ok(pool)
816}
817
818fn read_u2_table(reader: &mut ByteReader<'_>) -> Result<Vec<u16>, ClassReadError> {
819 let count = reader.read_u2()? as usize;
820 let mut values = Vec::with_capacity(count);
821 for _ in 0..count {
822 values.push(reader.read_u2()?);
823 }
824 Ok(values)
825}
826
827fn read_fields(
828 reader: &mut ByteReader<'_>,
829 cp: &[CpInfo],
830) -> Result<Vec<FieldInfo>, ClassReadError> {
831 let count = reader.read_u2()? as usize;
832 let mut fields = Vec::with_capacity(count);
833 for _ in 0..count {
834 let access_flags = reader.read_u2()?;
835 let name_index = reader.read_u2()?;
836 let descriptor_index = reader.read_u2()?;
837 let attributes = read_attributes(reader, cp)?;
838 fields.push(FieldInfo {
839 access_flags,
840 name_index,
841 descriptor_index,
842 attributes,
843 });
844 }
845 Ok(fields)
846}
847
848fn read_methods(
849 reader: &mut ByteReader<'_>,
850 cp: &[CpInfo],
851) -> Result<Vec<MethodInfo>, ClassReadError> {
852 let count = reader.read_u2()? as usize;
853 let mut methods = Vec::with_capacity(count);
854 for _ in 0..count {
855 let access_flags = reader.read_u2()?;
856 let name_index = reader.read_u2()?;
857 let descriptor_index = reader.read_u2()?;
858 let attributes = read_attributes(reader, cp)?;
859 methods.push(MethodInfo {
860 access_flags,
861 name_index,
862 descriptor_index,
863 attributes,
864 });
865 }
866 Ok(methods)
867}
868
869fn read_attributes(
870 reader: &mut ByteReader<'_>,
871 cp: &[CpInfo],
872) -> Result<Vec<AttributeInfo>, ClassReadError> {
873 let count = reader.read_u2()? as usize;
874 let mut attributes = Vec::with_capacity(count);
875 for _ in 0..count {
876 let name_index = reader.read_u2()?;
877 let length = reader.read_u4()? as usize;
878 let name = cp_utf8(cp, name_index)?;
879 let info = reader.read_bytes(length)?;
880 let attribute = parse_attribute(name, info, cp)?;
881 attributes.push(attribute);
882 }
883 Ok(attributes)
884}
885
886fn parse_attribute(
887 name: &str,
888 info: Vec<u8>,
889 cp: &[CpInfo],
890) -> Result<AttributeInfo, ClassReadError> {
891 let mut reader = ByteReader::new(&info);
892 let attribute = match name {
893 "Code" => {
894 let max_stack = reader.read_u2()?;
895 let max_locals = reader.read_u2()?;
896 let code_length = reader.read_u4()? as usize;
897 let code = reader.read_bytes(code_length)?;
898 let instructions = parse_code_instructions(&code)?;
899 let exception_table_length = reader.read_u2()? as usize;
900 let mut exception_table = Vec::with_capacity(exception_table_length);
901 for _ in 0..exception_table_length {
902 exception_table.push(ExceptionTableEntry {
903 start_pc: reader.read_u2()?,
904 end_pc: reader.read_u2()?,
905 handler_pc: reader.read_u2()?,
906 catch_type: reader.read_u2()?,
907 });
908 }
909 let attributes = read_attributes(&mut reader, cp)?;
910 let (insn_nodes, try_catch_blocks) = build_insn_nodes(&code, &exception_table, cp)?;
911 AttributeInfo::Code(CodeAttribute {
912 max_stack,
913 max_locals,
914 code,
915 instructions,
916 insn_nodes,
917 exception_table,
918 try_catch_blocks,
919 attributes,
920 })
921 }
922 "ConstantValue" => AttributeInfo::ConstantValue {
923 constantvalue_index: reader.read_u2()?,
924 },
925 "Exceptions" => {
926 let count = reader.read_u2()? as usize;
927 let mut exception_index_table = Vec::with_capacity(count);
928 for _ in 0..count {
929 exception_index_table.push(reader.read_u2()?);
930 }
931 AttributeInfo::Exceptions {
932 exception_index_table,
933 }
934 }
935 "SourceFile" => AttributeInfo::SourceFile {
936 sourcefile_index: reader.read_u2()?,
937 },
938 "LineNumberTable" => {
939 let count = reader.read_u2()? as usize;
940 let mut entries = Vec::with_capacity(count);
941 for _ in 0..count {
942 entries.push(LineNumber {
943 start_pc: reader.read_u2()?,
944 line_number: reader.read_u2()?,
945 });
946 }
947 AttributeInfo::LineNumberTable { entries }
948 }
949 "LocalVariableTable" => {
950 let count = reader.read_u2()? as usize;
951 let mut entries = Vec::with_capacity(count);
952 for _ in 0..count {
953 entries.push(LocalVariable {
954 start_pc: reader.read_u2()?,
955 length: reader.read_u2()?,
956 name_index: reader.read_u2()?,
957 descriptor_index: reader.read_u2()?,
958 index: reader.read_u2()?,
959 });
960 }
961 AttributeInfo::LocalVariableTable { entries }
962 }
963 "Signature" => AttributeInfo::Signature {
964 signature_index: reader.read_u2()?,
965 },
966 "StackMapTable" => {
967 let count = reader.read_u2()? as usize;
968 let mut entries = Vec::with_capacity(count);
969 for _ in 0..count {
970 let frame_type = reader.read_u1()?;
971 let frame = match frame_type {
972 0..=63 => StackMapFrame::SameFrame {
973 offset_delta: frame_type as u16,
974 },
975 64..=127 => StackMapFrame::SameLocals1StackItemFrame {
976 offset_delta: (frame_type - 64) as u16,
977 stack: parse_verification_type(&mut reader)?,
978 },
979 247 => StackMapFrame::SameLocals1StackItemFrameExtended {
980 offset_delta: reader.read_u2()?,
981 stack: parse_verification_type(&mut reader)?,
982 },
983 248..=250 => StackMapFrame::ChopFrame {
984 offset_delta: reader.read_u2()?,
985 k: 251 - frame_type,
986 },
987 251 => StackMapFrame::SameFrameExtended {
988 offset_delta: reader.read_u2()?,
989 },
990 252..=254 => {
991 let offset_delta = reader.read_u2()?;
992 let locals_count = (frame_type - 251) as usize;
993 let mut locals = Vec::with_capacity(locals_count);
994 for _ in 0..locals_count {
995 locals.push(parse_verification_type(&mut reader)?);
996 }
997 StackMapFrame::AppendFrame {
998 offset_delta,
999 locals,
1000 }
1001 }
1002 255 => {
1003 let offset_delta = reader.read_u2()?;
1004 let locals_count = reader.read_u2()? as usize;
1005 let mut locals = Vec::with_capacity(locals_count);
1006 for _ in 0..locals_count {
1007 locals.push(parse_verification_type(&mut reader)?);
1008 }
1009 let stack_count = reader.read_u2()? as usize;
1010 let mut stack = Vec::with_capacity(stack_count);
1011 for _ in 0..stack_count {
1012 stack.push(parse_verification_type(&mut reader)?);
1013 }
1014 StackMapFrame::FullFrame {
1015 offset_delta,
1016 locals,
1017 stack,
1018 }
1019 }
1020 _ => {
1021 return Err(ClassReadError::InvalidAttribute(
1022 "StackMapTable".to_string(),
1023 ));
1024 }
1025 };
1026 entries.push(frame);
1027 }
1028 AttributeInfo::StackMapTable { entries }
1029 }
1030 "Deprecated" => AttributeInfo::Deprecated,
1031 "Synthetic" => AttributeInfo::Synthetic,
1032 "InnerClasses" => {
1033 let count = reader.read_u2()? as usize;
1034 let mut classes = Vec::with_capacity(count);
1035 for _ in 0..count {
1036 classes.push(InnerClass {
1037 inner_class_info_index: reader.read_u2()?,
1038 outer_class_info_index: reader.read_u2()?,
1039 inner_name_index: reader.read_u2()?,
1040 inner_class_access_flags: reader.read_u2()?,
1041 });
1042 }
1043 AttributeInfo::InnerClasses { classes }
1044 }
1045 "EnclosingMethod" => AttributeInfo::EnclosingMethod {
1046 class_index: reader.read_u2()?,
1047 method_index: reader.read_u2()?,
1048 },
1049 "BootstrapMethods" => {
1050 let count = reader.read_u2()? as usize;
1051 let mut methods = Vec::with_capacity(count);
1052 for _ in 0..count {
1053 let bootstrap_method_ref = reader.read_u2()?;
1054 let arg_count = reader.read_u2()? as usize;
1055 let mut bootstrap_arguments = Vec::with_capacity(arg_count);
1056 for _ in 0..arg_count {
1057 bootstrap_arguments.push(reader.read_u2()?);
1058 }
1059 methods.push(BootstrapMethod {
1060 bootstrap_method_ref,
1061 bootstrap_arguments,
1062 });
1063 }
1064 AttributeInfo::BootstrapMethods { methods }
1065 }
1066 "MethodParameters" => {
1067 let count = reader.read_u1()? as usize;
1068 let mut parameters = Vec::with_capacity(count);
1069 for _ in 0..count {
1070 parameters.push(MethodParameter {
1071 name_index: reader.read_u2()?,
1072 access_flags: reader.read_u2()?,
1073 });
1074 }
1075 AttributeInfo::MethodParameters { parameters }
1076 }
1077 "RuntimeVisibleAnnotations" => {
1078 let annotations = parse_annotations(&mut reader)?;
1079 AttributeInfo::RuntimeVisibleAnnotations { annotations }
1080 }
1081 "RuntimeInvisibleAnnotations" => {
1082 let annotations = parse_annotations(&mut reader)?;
1083 AttributeInfo::RuntimeInvisibleAnnotations { annotations }
1084 }
1085 "RuntimeVisibleParameterAnnotations" => {
1086 let parameters = parse_parameter_annotations(&mut reader)?;
1087 AttributeInfo::RuntimeVisibleParameterAnnotations { parameters }
1088 }
1089 "RuntimeInvisibleParameterAnnotations" => {
1090 let parameters = parse_parameter_annotations(&mut reader)?;
1091 AttributeInfo::RuntimeInvisibleParameterAnnotations { parameters }
1092 }
1093 "RuntimeVisibleTypeAnnotations" => {
1094 let annotations = parse_type_annotations(&mut reader)?;
1095 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations }
1096 }
1097 "RuntimeInvisibleTypeAnnotations" => {
1098 let annotations = parse_type_annotations(&mut reader)?;
1099 AttributeInfo::RuntimeInvisibleTypeAnnotations { annotations }
1100 }
1101 _ => {
1102 return Ok(AttributeInfo::Unknown {
1103 name: name.to_string(),
1104 info,
1105 });
1106 }
1107 };
1108
1109 if reader.remaining() != 0 {
1110 return Err(ClassReadError::InvalidAttribute(name.to_string()));
1111 }
1112
1113 Ok(attribute)
1114}
1115
1116fn parse_annotations(reader: &mut ByteReader) -> Result<Vec<Annotation>, ClassReadError> {
1117 let num = reader.read_u2()? as usize;
1118 let mut out = Vec::with_capacity(num);
1119 for _ in 0..num {
1120 out.push(parse_annotation(reader)?);
1121 }
1122 Ok(out)
1123}
1124
1125fn parse_annotation(reader: &mut ByteReader) -> Result<Annotation, ClassReadError> {
1126 let type_descriptor_index = reader.read_u2()?;
1127 let num_pairs = reader.read_u2()? as usize;
1128 let mut element_value_pairs = Vec::with_capacity(num_pairs);
1129 for _ in 0..num_pairs {
1130 let element_name_index = reader.read_u2()?;
1131 let value = parse_element_value(reader)?;
1132 element_value_pairs.push(ElementValuePair {
1133 element_name_index,
1134 value,
1135 });
1136 }
1137 Ok(Annotation {
1138 type_descriptor_index,
1139 element_value_pairs,
1140 })
1141}
1142
1143fn parse_parameter_annotations(
1144 reader: &mut ByteReader,
1145) -> Result<ParameterAnnotations, ClassReadError> {
1146 let num_params = reader.read_u1()? as usize;
1147 let mut parameters = Vec::with_capacity(num_params);
1148 for _ in 0..num_params {
1149 let num_ann = reader.read_u2()? as usize;
1150 let mut anns = Vec::with_capacity(num_ann);
1151 for _ in 0..num_ann {
1152 anns.push(parse_annotation(reader)?);
1153 }
1154 parameters.push(anns);
1155 }
1156 Ok(ParameterAnnotations { parameters })
1157}
1158
1159fn parse_type_annotations(reader: &mut ByteReader) -> Result<Vec<TypeAnnotation>, ClassReadError> {
1160 let num = reader.read_u2()? as usize;
1161 let mut out = Vec::with_capacity(num);
1162 for _ in 0..num {
1163 out.push(parse_type_annotation(reader)?);
1164 }
1165 Ok(out)
1166}
1167
1168fn parse_type_annotation(reader: &mut ByteReader) -> Result<TypeAnnotation, ClassReadError> {
1169 let target_type = reader.read_u1()?;
1170 let target_info = parse_type_annotation_target_info(reader, target_type)?;
1171 let target_path = parse_type_path(reader)?;
1172 let annotation = parse_annotation(reader)?;
1173 Ok(TypeAnnotation {
1174 target_type,
1175 target_info,
1176 target_path,
1177 annotation,
1178 })
1179}
1180
1181fn parse_type_path(reader: &mut ByteReader) -> Result<TypePath, ClassReadError> {
1182 let path_length = reader.read_u1()? as usize;
1183 let mut path = Vec::with_capacity(path_length);
1184 for _ in 0..path_length {
1185 path.push(TypePathEntry {
1186 type_path_kind: reader.read_u1()?,
1187 type_argument_index: reader.read_u1()?,
1188 });
1189 }
1190 Ok(TypePath { path })
1191}
1192
1193fn parse_type_annotation_target_info(
1194 reader: &mut ByteReader,
1195 target_type: u8,
1196) -> Result<TypeAnnotationTargetInfo, ClassReadError> {
1197 use crate::constants::*;
1198
1199 let ti = match target_type {
1200 TA_TARGET_CLASS_TYPE_PARAMETER | TA_TARGET_METHOD_TYPE_PARAMETER => {
1201 TypeAnnotationTargetInfo::TypeParameter {
1202 type_parameter_index: reader.read_u1()?,
1203 }
1204 }
1205
1206 TA_TARGET_CLASS_EXTENDS => TypeAnnotationTargetInfo::Supertype {
1207 supertype_index: reader.read_u2()?,
1208 },
1209
1210 TA_TARGET_CLASS_TYPE_PARAMETER_BOUND | TA_TARGET_METHOD_TYPE_PARAMETER_BOUND => {
1211 TypeAnnotationTargetInfo::TypeParameterBound {
1212 type_parameter_index: reader.read_u1()?,
1213 bound_index: reader.read_u1()?,
1214 }
1215 }
1216
1217 TA_TARGET_FIELD | TA_TARGET_METHOD_RETURN | TA_TARGET_METHOD_RECEIVER => {
1218 TypeAnnotationTargetInfo::Empty
1219 }
1220
1221 TA_TARGET_METHOD_FORMAL_PARAMETER => TypeAnnotationTargetInfo::FormalParameter {
1222 formal_parameter_index: reader.read_u1()?,
1223 },
1224
1225 TA_TARGET_THROWS => TypeAnnotationTargetInfo::Throws {
1226 throws_type_index: reader.read_u2()?,
1227 },
1228
1229 TA_TARGET_LOCAL_VARIABLE | TA_TARGET_RESOURCE_VARIABLE => {
1230 let table_length = reader.read_u2()? as usize;
1231 let mut table = Vec::with_capacity(table_length);
1232 for _ in 0..table_length {
1233 table.push(LocalVarTargetTableEntry {
1234 start_pc: reader.read_u2()?,
1235 length: reader.read_u2()?,
1236 index: reader.read_u2()?,
1237 });
1238 }
1239 TypeAnnotationTargetInfo::LocalVar { table }
1240 }
1241
1242 TA_TARGET_EXCEPTION_PARAMETER => TypeAnnotationTargetInfo::Catch {
1243 exception_table_index: reader.read_u2()?,
1244 },
1245
1246 TA_TARGET_INSTANCEOF
1247 | TA_TARGET_NEW
1248 | TA_TARGET_CONSTRUCTOR_REFERENCE_RECEIVER
1249 | TA_TARGET_METHOD_REFERENCE_RECEIVER => TypeAnnotationTargetInfo::Offset {
1250 offset: reader.read_u2()?,
1251 },
1252
1253 TA_TARGET_CAST
1254 | TA_TARGET_CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1255 | TA_TARGET_METHOD_INVOCATION_TYPE_ARGUMENT
1256 | TA_TARGET_CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1257 | TA_TARGET_METHOD_REFERENCE_TYPE_ARGUMENT => TypeAnnotationTargetInfo::TypeArgument {
1258 offset: reader.read_u2()?,
1259 type_argument_index: reader.read_u1()?,
1260 },
1261
1262 _ => {
1263 return Err(ClassReadError::InvalidAttribute(format!(
1264 "TypeAnnotationTargetInfo(target_type=0x{:02X})",
1265 target_type
1266 )));
1267 }
1268 };
1269
1270 Ok(ti)
1271}
1272
1273fn parse_element_value(reader: &mut ByteReader) -> Result<ElementValue, ClassReadError> {
1274 let tag = reader.read_u1()?;
1275 let v = match tag {
1276 b'B' | b'C' | b'D' | b'F' | b'I' | b'J' | b'S' | b'Z' | b's' => {
1277 ElementValue::ConstValueIndex {
1278 tag,
1279 const_value_index: reader.read_u2()?,
1280 }
1281 }
1282 b'e' => ElementValue::EnumConstValue {
1283 type_name_index: reader.read_u2()?,
1284 const_name_index: reader.read_u2()?,
1285 },
1286 b'c' => ElementValue::ClassInfoIndex {
1287 class_info_index: reader.read_u2()?,
1288 },
1289 b'@' => ElementValue::AnnotationValue(Box::new(parse_annotation(reader)?)),
1290 b'[' => {
1291 let n = reader.read_u2()? as usize;
1292 let mut items = Vec::with_capacity(n);
1293 for _ in 0..n {
1294 items.push(parse_element_value(reader)?);
1295 }
1296 ElementValue::ArrayValue(items)
1297 }
1298 _ => {
1299 return Err(ClassReadError::InvalidAttribute(
1300 "AnnotationElementValue".to_string(),
1301 ));
1302 }
1303 };
1304 Ok(v)
1305}
1306
1307fn parse_verification_type(
1308 reader: &mut ByteReader<'_>,
1309) -> Result<VerificationTypeInfo, ClassReadError> {
1310 let tag = reader.read_u1()?;
1311 let kind = match tag {
1312 0 => VerificationTypeInfo::Top,
1313 1 => VerificationTypeInfo::Integer,
1314 2 => VerificationTypeInfo::Float,
1315 3 => VerificationTypeInfo::Double,
1316 4 => VerificationTypeInfo::Long,
1317 5 => VerificationTypeInfo::Null,
1318 6 => VerificationTypeInfo::UninitializedThis,
1319 7 => VerificationTypeInfo::Object {
1320 cpool_index: reader.read_u2()?,
1321 },
1322 8 => VerificationTypeInfo::Uninitialized {
1323 offset: reader.read_u2()?,
1324 },
1325 _ => {
1326 return Err(ClassReadError::InvalidAttribute(
1327 "StackMapTable".to_string(),
1328 ));
1329 }
1330 };
1331 Ok(kind)
1332}
1333
1334fn cp_utf8(cp: &[CpInfo], index: u16) -> Result<&str, ClassReadError> {
1335 match cp.get(index as usize) {
1336 Some(CpInfo::Utf8(value)) => Ok(value.as_str()),
1337 _ => Err(ClassReadError::InvalidIndex(index)),
1338 }
1339}
1340
1341fn cp_class_name(cp: &[CpInfo], index: u16) -> Result<&str, ClassReadError> {
1342 match cp.get(index as usize) {
1343 Some(CpInfo::Class { name_index }) => cp_utf8(cp, *name_index),
1344 _ => Err(ClassReadError::InvalidIndex(index)),
1345 }
1346}
1347
1348fn cp_name_and_type(cp: &[CpInfo], index: u16) -> Result<(&str, &str), ClassReadError> {
1349 match cp.get(index as usize) {
1350 Some(CpInfo::NameAndType {
1351 name_index,
1352 descriptor_index,
1353 }) => Ok((cp_utf8(cp, *name_index)?, cp_utf8(cp, *descriptor_index)?)),
1354 _ => Err(ClassReadError::InvalidIndex(index)),
1355 }
1356}
1357
1358fn cp_field_ref(cp: &[CpInfo], index: u16) -> Result<(&str, &str, &str), ClassReadError> {
1359 match cp.get(index as usize) {
1360 Some(CpInfo::Fieldref {
1361 class_index,
1362 name_and_type_index,
1363 }) => {
1364 let owner = cp_class_name(cp, *class_index)?;
1365 let (name, desc) = cp_name_and_type(cp, *name_and_type_index)?;
1366 Ok((owner, name, desc))
1367 }
1368 _ => Err(ClassReadError::InvalidIndex(index)),
1369 }
1370}
1371
1372fn cp_method_ref(cp: &[CpInfo], index: u16) -> Result<(&str, &str, &str, bool), ClassReadError> {
1373 match cp.get(index as usize) {
1374 Some(CpInfo::Methodref {
1375 class_index,
1376 name_and_type_index,
1377 }) => {
1378 let owner = cp_class_name(cp, *class_index)?;
1379 let (name, desc) = cp_name_and_type(cp, *name_and_type_index)?;
1380 Ok((owner, name, desc, false))
1381 }
1382 Some(CpInfo::InterfaceMethodref {
1383 class_index,
1384 name_and_type_index,
1385 }) => {
1386 let owner = cp_class_name(cp, *class_index)?;
1387 let (name, desc) = cp_name_and_type(cp, *name_and_type_index)?;
1388 Ok((owner, name, desc, true))
1389 }
1390 _ => Err(ClassReadError::InvalidIndex(index)),
1391 }
1392}
1393
1394fn cp_invoke_dynamic(cp: &[CpInfo], index: u16) -> Result<(&str, &str), ClassReadError> {
1395 match cp.get(index as usize) {
1396 Some(CpInfo::InvokeDynamic {
1397 name_and_type_index,
1398 ..
1399 }) => cp_name_and_type(cp, *name_and_type_index),
1400 _ => Err(ClassReadError::InvalidIndex(index)),
1401 }
1402}
1403
1404fn cp_ldc_constant(cp: &[CpInfo], index: u16) -> Result<LdcConstant, ClassReadError> {
1405 match cp.get(index as usize) {
1406 Some(CpInfo::Integer(value)) => Ok(LdcConstant::Integer(*value)),
1407 Some(CpInfo::Float(value)) => Ok(LdcConstant::Float(*value)),
1408 Some(CpInfo::Long(value)) => Ok(LdcConstant::Long(*value)),
1409 Some(CpInfo::Double(value)) => Ok(LdcConstant::Double(*value)),
1410 Some(CpInfo::String { string_index }) => {
1411 Ok(LdcConstant::String(cp_utf8(cp, *string_index)?.to_string()))
1412 }
1413 Some(CpInfo::Class { name_index }) => {
1414 Ok(LdcConstant::Class(cp_utf8(cp, *name_index)?.to_string()))
1415 }
1416 Some(CpInfo::MethodType { descriptor_index }) => Ok(LdcConstant::MethodType(
1417 cp_utf8(cp, *descriptor_index)?.to_string(),
1418 )),
1419 Some(CpInfo::MethodHandle {
1420 reference_kind,
1421 reference_index,
1422 }) => Ok(LdcConstant::MethodHandle {
1423 reference_kind: *reference_kind,
1424 reference_index: *reference_index,
1425 }),
1426 Some(CpInfo::Dynamic { .. }) => Ok(LdcConstant::Dynamic),
1427 _ => Err(ClassReadError::InvalidIndex(index)),
1428 }
1429}
1430
1431fn decode_modified_utf8(bytes: &[u8]) -> Result<String, ClassReadError> {
1432 let mut code_units = Vec::with_capacity(bytes.len());
1433 let mut i = 0;
1434 while i < bytes.len() {
1435 let byte = bytes[i];
1436 if byte & 0x80 == 0 {
1437 code_units.push(byte as u16);
1438 i += 1;
1439 } else if byte & 0xE0 == 0xC0 {
1440 if i + 1 >= bytes.len() {
1441 return Err(ClassReadError::Utf8Error("truncated 2-byte".to_string()));
1442 }
1443 let byte2 = bytes[i + 1];
1444 if byte2 & 0xC0 != 0x80 {
1445 return Err(ClassReadError::Utf8Error("invalid 2-byte".to_string()));
1446 }
1447 let value = (((byte & 0x1F) as u16) << 6) | ((byte2 & 0x3F) as u16);
1448 code_units.push(value);
1449 i += 2;
1450 } else if byte & 0xF0 == 0xE0 {
1451 if i + 2 >= bytes.len() {
1452 return Err(ClassReadError::Utf8Error("truncated 3-byte".to_string()));
1453 }
1454 let byte2 = bytes[i + 1];
1455 let byte3 = bytes[i + 2];
1456 if byte2 & 0xC0 != 0x80 || byte3 & 0xC0 != 0x80 {
1457 return Err(ClassReadError::Utf8Error("invalid 3-byte".to_string()));
1458 }
1459 let value = (((byte & 0x0F) as u16) << 12)
1460 | (((byte2 & 0x3F) as u16) << 6)
1461 | ((byte3 & 0x3F) as u16);
1462 code_units.push(value);
1463 i += 3;
1464 } else {
1465 return Err(ClassReadError::Utf8Error(
1466 "invalid leading byte".to_string(),
1467 ));
1468 }
1469 }
1470
1471 String::from_utf16(&code_units)
1472 .map_err(|_| ClassReadError::Utf8Error("invalid utf16".to_string()))
1473}
1474
1475fn parse_code_instructions(code: &[u8]) -> Result<Vec<Insn>, ClassReadError> {
1476 let mut reader = ByteReader::new(code);
1477 let mut insns = Vec::new();
1478
1479 while reader.remaining() > 0 {
1480 let opcode_offset = reader.pos();
1481 let opcode = reader.read_u1()?;
1482 let insn = match opcode {
1483 opcodes::NOP..=opcodes::DCONST_1 => Insn::Simple(opcode.into()),
1484 opcodes::BIPUSH => Insn::Int(IntInsnNode {
1485 insn: opcode.into(),
1486 operand: reader.read_i1()? as i32,
1487 }),
1488 opcodes::SIPUSH => Insn::Int(IntInsnNode {
1489 insn: opcode.into(),
1490 operand: reader.read_i2()? as i32,
1491 }),
1492 opcodes::LDC => Insn::Ldc(LdcInsnNode {
1493 insn: opcode.into(),
1494 value: LdcValue::Index(reader.read_u1()? as u16),
1495 }),
1496 opcodes::LDC_W | opcodes::LDC2_W => Insn::Ldc(LdcInsnNode {
1497 insn: opcode.into(),
1498 value: LdcValue::Index(reader.read_u2()?),
1499 }),
1500 opcodes::ILOAD..=opcodes::ALOAD => Insn::Var(VarInsnNode {
1501 insn: opcode.into(),
1502 var_index: reader.read_u1()? as u16,
1503 }),
1504 opcodes::ILOAD_0..=opcodes::SALOAD => Insn::Simple(opcode.into()),
1505 opcodes::ISTORE..=opcodes::ASTORE => Insn::Var(VarInsnNode {
1506 insn: opcode.into(),
1507 var_index: reader.read_u1()? as u16,
1508 }),
1509 opcodes::ISTORE_0..=opcodes::SASTORE => Insn::Simple(opcode.into()),
1510 opcodes::POP..=opcodes::LXOR => Insn::Simple(opcode.into()),
1511 opcodes::IINC => Insn::Iinc(IincInsnNode {
1512 insn: opcode.into(),
1513 var_index: reader.read_u1()? as u16,
1514 increment: reader.read_i1()? as i16,
1515 }),
1516 opcodes::I2L..=opcodes::DCMPG => Insn::Simple(opcode.into()),
1517 opcodes::IFEQ..=opcodes::JSR => Insn::Jump(JumpInsnNode {
1518 insn: opcode.into(),
1519 offset: reader.read_i2()? as i32,
1520 }),
1521 opcodes::RET => Insn::Var(VarInsnNode {
1522 insn: opcode.into(),
1523 var_index: reader.read_u1()? as u16,
1524 }),
1525 opcodes::TABLESWITCH => read_table_switch(&mut reader, opcode_offset)?,
1526 opcodes::LOOKUPSWITCH => read_lookup_switch(&mut reader, opcode_offset)?,
1527 opcodes::IRETURN..=opcodes::RETURN => Insn::Simple(InsnNode { opcode }),
1528 opcodes::GETSTATIC..=opcodes::PUTFIELD => Insn::Field(FieldInsnNode {
1529 insn: opcode.into(),
1530 field_ref: MemberRef::Index(reader.read_u2()?),
1531 }),
1532 opcodes::INVOKEVIRTUAL..=opcodes::INVOKESTATIC => Insn::Method(MethodInsnNode {
1533 insn: opcode.into(),
1534 method_ref: MemberRef::Index(reader.read_u2()?),
1535 }),
1536 opcodes::INVOKEINTERFACE => {
1537 let method_index = reader.read_u2()?;
1538 let count = reader.read_u1()?;
1539 let _ = reader.read_u1()?;
1540 Insn::InvokeInterface(InvokeInterfaceInsnNode {
1541 insn: opcode.into(),
1542 method_index,
1543 count,
1544 })
1545 }
1546 opcodes::INVOKEDYNAMIC => {
1547 let method_index = reader.read_u2()?;
1548 let _ = reader.read_u2()?;
1549 Insn::InvokeDynamic(InvokeDynamicInsnNode::from_index(method_index))
1550 }
1551 opcodes::NEW => Insn::Type(TypeInsnNode {
1552 insn: opcode.into(),
1553 type_index: reader.read_u2()?,
1554 }),
1555 opcodes::NEWARRAY => Insn::Int(IntInsnNode {
1556 insn: opcode.into(),
1557 operand: reader.read_u1()? as i32,
1558 }),
1559 opcodes::ANEWARRAY => Insn::Type(TypeInsnNode {
1560 insn: opcode.into(),
1561 type_index: reader.read_u2()?,
1562 }),
1563 opcodes::ARRAYLENGTH | opcodes::ATHROW => Insn::Simple(opcode.into()),
1564 opcodes::CHECKCAST | opcodes::INSTANCEOF => Insn::Type(TypeInsnNode {
1565 insn: opcode.into(),
1566 type_index: reader.read_u2()?,
1567 }),
1568 opcodes::MONITORENTER | opcodes::MONITOREXIT => Insn::Simple(opcode.into()),
1569 opcodes::WIDE => read_wide(&mut reader)?,
1570 opcodes::MULTIANEWARRAY => Insn::MultiANewArray(MultiANewArrayInsnNode {
1571 insn: opcode.into(),
1572 type_index: reader.read_u2()?,
1573 dimensions: reader.read_u1()?,
1574 }),
1575 opcodes::IFNULL | opcodes::IFNONNULL => Insn::Jump(JumpInsnNode {
1576 insn: opcode.into(),
1577 offset: reader.read_i2()? as i32,
1578 }),
1579 opcodes::GOTO_W | opcodes::JSR_W => Insn::Jump(JumpInsnNode {
1580 insn: opcode.into(),
1581 offset: reader.read_i4()?,
1582 }),
1583 opcodes::BREAKPOINT => Insn::Simple(opcode.into()),
1584 opcodes::IMPDEP1 | opcodes::IMPDEP2 => Insn::Simple(opcode.into()),
1585 _ => {
1586 return Err(ClassReadError::InvalidOpcode {
1587 opcode,
1588 offset: opcode_offset,
1589 });
1590 }
1591 };
1592
1593 insns.push(insn);
1594 }
1595
1596 Ok(insns)
1597}
1598
1599pub(crate) fn parse_code_instructions_public(code: &[u8]) -> Result<Vec<Insn>, ClassReadError> {
1600 parse_code_instructions(code)
1601}
1602
1603#[derive(Debug, Clone)]
1604struct ParsedInstruction {
1605 offset: u16,
1606 insn: Insn,
1607}
1608
1609fn parse_code_instructions_with_offsets(
1610 code: &[u8],
1611) -> Result<Vec<ParsedInstruction>, ClassReadError> {
1612 let mut reader = ByteReader::new(code);
1613 let mut insns = Vec::new();
1614
1615 while reader.remaining() > 0 {
1616 let opcode_offset = reader.pos();
1617 let opcode = reader.read_u1()?;
1618 let insn = match opcode {
1619 opcodes::NOP..=opcodes::DCONST_1 => Insn::Simple(opcode.into()),
1620 opcodes::BIPUSH => Insn::Int(IntInsnNode {
1621 insn: opcode.into(),
1622 operand: reader.read_i1()? as i32,
1623 }),
1624 opcodes::SIPUSH => Insn::Int(IntInsnNode {
1625 insn: opcode.into(),
1626 operand: reader.read_i2()? as i32,
1627 }),
1628 opcodes::LDC => Insn::Ldc(LdcInsnNode {
1629 insn: opcode.into(),
1630 value: LdcValue::Index(reader.read_u1()? as u16),
1631 }),
1632 opcodes::LDC_W | opcodes::LDC2_W => Insn::Ldc(LdcInsnNode {
1633 insn: opcode.into(),
1634 value: LdcValue::Index(reader.read_u2()?),
1635 }),
1636 opcodes::ILOAD..=opcodes::ALOAD => Insn::Var(VarInsnNode {
1637 insn: opcode.into(),
1638 var_index: reader.read_u1()? as u16,
1639 }),
1640 opcodes::ILOAD_0..=opcodes::SALOAD => Insn::Simple(opcode.into()),
1641 opcodes::ISTORE..=opcodes::ASTORE => Insn::Var(VarInsnNode {
1642 insn: opcode.into(),
1643 var_index: reader.read_u1()? as u16,
1644 }),
1645 opcodes::ISTORE_0..=opcodes::SASTORE => Insn::Simple(opcode.into()),
1646 opcodes::POP..=opcodes::LXOR => Insn::Simple(opcode.into()),
1647 opcodes::IINC => Insn::Iinc(IincInsnNode {
1648 insn: opcode.into(),
1649 var_index: reader.read_u1()? as u16,
1650 increment: reader.read_i1()? as i16,
1651 }),
1652 opcodes::I2L..=opcodes::DCMPG => Insn::Simple(opcode.into()),
1653 opcodes::IFEQ..=opcodes::JSR => Insn::Jump(JumpInsnNode {
1654 insn: opcode.into(),
1655 offset: reader.read_i2()? as i32,
1656 }),
1657 opcodes::RET => Insn::Var(VarInsnNode {
1658 insn: opcode.into(),
1659 var_index: reader.read_u1()? as u16,
1660 }),
1661 opcodes::TABLESWITCH => read_table_switch(&mut reader, opcode_offset)?,
1662 opcodes::LOOKUPSWITCH => read_lookup_switch(&mut reader, opcode_offset)?,
1663 opcodes::IRETURN..=opcodes::RETURN => Insn::Simple(opcode.into()),
1664 opcodes::GETSTATIC..=opcodes::PUTFIELD => Insn::Field(FieldInsnNode {
1665 insn: opcode.into(),
1666 field_ref: MemberRef::Index(reader.read_u2()?),
1667 }),
1668 opcodes::INVOKEVIRTUAL..=opcodes::INVOKESTATIC => Insn::Method(MethodInsnNode {
1669 insn: opcode.into(),
1670 method_ref: MemberRef::Index(reader.read_u2()?),
1671 }),
1672 opcodes::INVOKEINTERFACE => {
1673 let method_index = reader.read_u2()?;
1674 let count = reader.read_u1()?;
1675 let _ = reader.read_u1()?;
1676 Insn::InvokeInterface(InvokeInterfaceInsnNode {
1677 insn: opcode.into(),
1678 method_index,
1679 count,
1680 })
1681 }
1682 opcodes::INVOKEDYNAMIC => {
1683 let method_index = reader.read_u2()?;
1684 let _ = reader.read_u2()?;
1685 Insn::InvokeDynamic(InvokeDynamicInsnNode::from_index(method_index))
1686 }
1687 opcodes::NEW => Insn::Type(TypeInsnNode {
1688 insn: opcode.into(),
1689 type_index: reader.read_u2()?,
1690 }),
1691 opcodes::NEWARRAY => Insn::Int(IntInsnNode {
1692 insn: opcode.into(),
1693 operand: reader.read_u1()? as i32,
1694 }),
1695 opcodes::ANEWARRAY => Insn::Type(TypeInsnNode {
1696 insn: opcode.into(),
1697 type_index: reader.read_u2()?,
1698 }),
1699 opcodes::ARRAYLENGTH | opcodes::ATHROW => Insn::Simple(opcode.into()),
1700 opcodes::CHECKCAST | opcodes::INSTANCEOF => Insn::Type(TypeInsnNode {
1701 insn: opcode.into(),
1702 type_index: reader.read_u2()?,
1703 }),
1704 opcodes::MONITORENTER | opcodes::MONITOREXIT => Insn::Simple(opcode.into()),
1705 opcodes::WIDE => read_wide(&mut reader)?,
1706 opcodes::MULTIANEWARRAY => Insn::MultiANewArray(MultiANewArrayInsnNode {
1707 insn: opcode.into(),
1708 type_index: reader.read_u2()?,
1709 dimensions: reader.read_u1()?,
1710 }),
1711 opcodes::IFNULL | opcodes::IFNONNULL => Insn::Jump(JumpInsnNode {
1712 insn: opcode.into(),
1713 offset: reader.read_i2()? as i32,
1714 }),
1715 opcodes::GOTO_W | opcodes::JSR_W => Insn::Jump(JumpInsnNode {
1716 insn: opcode.into(),
1717 offset: reader.read_i4()?,
1718 }),
1719 opcodes::BREAKPOINT => Insn::Simple(opcode.into()),
1720 opcodes::IMPDEP1 | opcodes::IMPDEP2 => Insn::Simple(opcode.into()),
1721 _ => {
1722 return Err(ClassReadError::InvalidOpcode {
1723 opcode,
1724 offset: opcode_offset,
1725 });
1726 }
1727 };
1728
1729 insns.push(ParsedInstruction {
1730 offset: opcode_offset as u16,
1731 insn,
1732 });
1733 }
1734
1735 Ok(insns)
1736}
1737
1738fn build_insn_nodes(
1739 code: &[u8],
1740 exception_table: &[ExceptionTableEntry],
1741 cp: &[CpInfo],
1742) -> Result<(Vec<AbstractInsnNode>, Vec<TryCatchBlockNode>), ClassReadError> {
1743 let instructions = parse_code_instructions_with_offsets(code)?;
1744 let mut offsets = std::collections::HashSet::new();
1745 for instruction in &instructions {
1746 offsets.insert(instruction.offset);
1747 match &instruction.insn {
1748 Insn::Jump(node) => {
1749 offsets.insert((instruction.offset as i32 + node.offset) as u16);
1750 }
1751 Insn::TableSwitch(node) => {
1752 offsets.insert((instruction.offset as i32 + node.default_offset) as u16);
1753 for offset in &node.offsets {
1754 offsets.insert((instruction.offset as i32 + *offset) as u16);
1755 }
1756 }
1757 Insn::LookupSwitch(node) => {
1758 offsets.insert((instruction.offset as i32 + node.default_offset) as u16);
1759 for (_, offset) in &node.pairs {
1760 offsets.insert((instruction.offset as i32 + *offset) as u16);
1761 }
1762 }
1763 _ => {}
1764 }
1765 }
1766 for entry in exception_table {
1767 offsets.insert(entry.start_pc);
1768 offsets.insert(entry.end_pc);
1769 offsets.insert(entry.handler_pc);
1770 }
1771 offsets.insert(code.len() as u16);
1772
1773 let mut label_by_offset = std::collections::HashMap::new();
1774 for (next_id, offset) in offsets.into_iter().enumerate() {
1775 label_by_offset.insert(offset, LabelNode { id: next_id });
1776 }
1777
1778 let mut nodes = Vec::new();
1779 for instruction in instructions {
1780 if let Some(label) = label_by_offset.get(&{ instruction.offset }) {
1781 nodes.push(AbstractInsnNode::Label(*label));
1782 }
1783 nodes.push(AbstractInsnNode::Insn(instruction.insn));
1784 }
1785 if let Some(label) = label_by_offset.get(&(code.len() as u16)) {
1786 nodes.push(AbstractInsnNode::Label(*label));
1787 }
1788
1789 let mut try_catch_blocks = Vec::new();
1790 for entry in exception_table {
1791 let start = *label_by_offset
1792 .get(&entry.start_pc)
1793 .ok_or_else(|| ClassReadError::InvalidAttribute("missing start label".to_string()))?;
1794 let end = *label_by_offset
1795 .get(&entry.end_pc)
1796 .ok_or_else(|| ClassReadError::InvalidAttribute("missing end label".to_string()))?;
1797 let handler = *label_by_offset
1798 .get(&entry.handler_pc)
1799 .ok_or_else(|| ClassReadError::InvalidAttribute("missing handler label".to_string()))?;
1800 let catch_type = if entry.catch_type == 0 {
1801 None
1802 } else {
1803 Some(cp_class_name(cp, entry.catch_type)?.to_string())
1804 };
1805 try_catch_blocks.push(TryCatchBlockNode {
1806 start,
1807 end,
1808 handler,
1809 catch_type,
1810 });
1811 }
1812
1813 Ok((nodes, try_catch_blocks))
1814}
1815
1816pub(crate) fn build_insn_nodes_public(
1817 code: &[u8],
1818 exception_table: &[ExceptionTableEntry],
1819 cp: &[CpInfo],
1820) -> Result<(Vec<AbstractInsnNode>, Vec<TryCatchBlockNode>), ClassReadError> {
1821 build_insn_nodes(code, exception_table, cp)
1822}
1823
1824fn read_table_switch(
1825 reader: &mut ByteReader<'_>,
1826 opcode_offset: usize,
1827) -> Result<Insn, ClassReadError> {
1828 reader.align4(opcode_offset)?;
1829 let default_offset = reader.read_i4()?;
1830 let low = reader.read_i4()?;
1831 let high = reader.read_i4()?;
1832 let count = if high < low {
1833 0
1834 } else {
1835 (high - low + 1) as usize
1836 };
1837 let mut offsets = Vec::with_capacity(count);
1838 for _ in 0..count {
1839 offsets.push(reader.read_i4()?);
1840 }
1841 Ok(Insn::TableSwitch(TableSwitchInsnNode {
1842 insn: opcodes::TABLESWITCH.into(),
1843 default_offset,
1844 low,
1845 high,
1846 offsets,
1847 }))
1848}
1849
1850fn read_lookup_switch(
1851 reader: &mut ByteReader<'_>,
1852 opcode_offset: usize,
1853) -> Result<Insn, ClassReadError> {
1854 reader.align4(opcode_offset)?;
1855 let default_offset = reader.read_i4()?;
1856 let npairs = reader.read_i4()? as usize;
1857 let mut pairs = Vec::with_capacity(npairs);
1858 for _ in 0..npairs {
1859 let key = reader.read_i4()?;
1860 let offset = reader.read_i4()?;
1861 pairs.push((key, offset));
1862 }
1863 Ok(Insn::LookupSwitch(LookupSwitchInsnNode {
1864 insn: opcodes::LOOKUPSWITCH.into(),
1865 default_offset,
1866 pairs,
1867 }))
1868}
1869
1870fn read_wide(reader: &mut ByteReader<'_>) -> Result<Insn, ClassReadError> {
1871 let opcode = reader.read_u1()?;
1872 match opcode {
1873 opcodes::ILOAD..=opcodes::ALOAD | opcodes::ISTORE..=opcodes::ASTORE | opcodes::RET => {
1874 Ok(Insn::Var(VarInsnNode {
1875 insn: opcode.into(),
1876 var_index: reader.read_u2()?,
1877 }))
1878 }
1879 opcodes::IINC => Ok(Insn::Iinc(IincInsnNode {
1880 insn: opcode.into(),
1881 var_index: reader.read_u2()?,
1882 increment: reader.read_i2()?,
1883 })),
1884 _ => Err(ClassReadError::InvalidOpcode {
1885 opcode,
1886 offset: reader.pos().saturating_sub(1),
1887 }),
1888 }
1889}
1890
1891fn visit_instruction(
1892 cp: &[CpInfo],
1893 offset: i32,
1894 insn: Insn,
1895 mv: &mut dyn MethodVisitor,
1896) -> Result<(), ClassReadError> {
1897 match insn {
1898 Insn::Simple(node) => {
1899 mv.visit_insn(node.opcode);
1900 }
1901 Insn::Int(node) => {
1902 mv.visit_int_insn(node.insn.opcode, node.operand);
1903 }
1904 Insn::Var(node) => {
1905 mv.visit_var_insn(node.insn.opcode, node.var_index);
1906 }
1907 Insn::Type(node) => {
1908 let type_name = cp_class_name(cp, node.type_index)?;
1909 mv.visit_type_insn(node.insn.opcode, type_name);
1910 }
1911 Insn::Field(node) => {
1912 let index = match node.field_ref {
1913 MemberRef::Index(index) => index,
1914 MemberRef::Symbolic { .. } => {
1915 return Err(ClassReadError::InvalidIndex(0));
1916 }
1917 };
1918 let (owner, name, desc) = cp_field_ref(cp, index)?;
1919 mv.visit_field_insn(node.insn.opcode, owner, name, desc);
1920 }
1921 Insn::Method(node) => {
1922 let index = match node.method_ref {
1923 MemberRef::Index(index) => index,
1924 MemberRef::Symbolic { .. } => {
1925 return Err(ClassReadError::InvalidIndex(0));
1926 }
1927 };
1928 let (owner, name, desc, is_interface) = cp_method_ref(cp, index)?;
1929 mv.visit_method_insn(node.insn.opcode, owner, name, desc, is_interface);
1930 }
1931 Insn::InvokeInterface(node) => {
1932 let (owner, name, desc, _is_interface) = cp_method_ref(cp, node.method_index)?;
1933 mv.visit_method_insn(node.insn.opcode, owner, name, desc, true);
1934 }
1935 Insn::InvokeDynamic(node) => {
1936 let (name, desc) = cp_invoke_dynamic(cp, node.method_index)?;
1937 mv.visit_invoke_dynamic_insn(name, desc);
1938 }
1939 Insn::Jump(node) => {
1940 let target = offset + node.offset;
1941 mv.visit_jump_insn(node.insn.opcode, target);
1942 }
1943 Insn::Ldc(node) => {
1944 let index = match node.value {
1945 LdcValue::Index(index) => index,
1946 LdcValue::String(value) => {
1947 mv.visit_ldc_insn(LdcConstant::String(value));
1948 return Ok(());
1949 }
1950 LdcValue::Type(value) => {
1951 match value.clone() {
1952 Type::Method { .. } => {
1953 mv.visit_ldc_insn(LdcConstant::MethodType(value.get_descriptor()));
1954 }
1955 _ => {
1956 mv.visit_ldc_insn(LdcConstant::Class(value.get_descriptor()));
1957 }
1958 }
1959
1960 return Ok(());
1961 }
1962 LdcValue::Int(value) => {
1963 mv.visit_ldc_insn(LdcConstant::Integer(value));
1964 return Ok(());
1965 }
1966 LdcValue::Float(value) => {
1967 mv.visit_ldc_insn(LdcConstant::Float(value));
1968 return Ok(());
1969 }
1970 LdcValue::Long(value) => {
1971 mv.visit_ldc_insn(LdcConstant::Long(value));
1972 return Ok(());
1973 }
1974 LdcValue::Double(value) => {
1975 mv.visit_ldc_insn(LdcConstant::Double(value));
1976 return Ok(());
1977 }
1978 };
1979 let constant = cp_ldc_constant(cp, index)?;
1980 mv.visit_ldc_insn(constant);
1981 }
1982 Insn::Iinc(node) => {
1983 mv.visit_iinc_insn(node.var_index, node.increment);
1984 }
1985 Insn::TableSwitch(node) => {
1986 let targets = node
1987 .offsets
1988 .iter()
1989 .map(|value| offset + *value)
1990 .collect::<Vec<_>>();
1991 mv.visit_table_switch(offset + node.default_offset, node.low, node.high, &targets);
1992 }
1993 Insn::LookupSwitch(node) => {
1994 let pairs = node
1995 .pairs
1996 .iter()
1997 .map(|(key, value)| (*key, offset + *value))
1998 .collect::<Vec<_>>();
1999 mv.visit_lookup_switch(offset + node.default_offset, &pairs);
2000 }
2001 Insn::MultiANewArray(node) => {
2002 let type_name = cp_class_name(cp, node.type_index)?;
2003 mv.visit_multi_anewarray_insn(type_name, node.dimensions);
2004 }
2005 }
2006 Ok(())
2007}
2008
2009pub struct ByteReader<'a> {
2010 data: &'a [u8],
2011 pos: usize,
2012}
2013
2014impl<'a> ByteReader<'a> {
2015 pub fn new(data: &'a [u8]) -> Self {
2016 Self { data, pos: 0 }
2017 }
2018
2019 pub fn remaining(&self) -> usize {
2020 self.data.len().saturating_sub(self.pos)
2021 }
2022
2023 pub fn pos(&self) -> usize {
2024 self.pos
2025 }
2026
2027 pub fn align4(&mut self, opcode_offset: usize) -> Result<(), ClassReadError> {
2028 let mut padding = (4 - ((opcode_offset + 1) % 4)) % 4;
2029 while padding > 0 {
2030 self.read_u1()?;
2031 padding -= 1;
2032 }
2033 Ok(())
2034 }
2035
2036 pub fn read_u1(&mut self) -> Result<u8, ClassReadError> {
2037 if self.pos >= self.data.len() {
2038 return Err(ClassReadError::UnexpectedEof);
2039 }
2040 let value = self.data[self.pos];
2041 self.pos += 1;
2042 Ok(value)
2043 }
2044
2045 pub fn read_i1(&mut self) -> Result<i8, ClassReadError> {
2046 Ok(self.read_u1()? as i8)
2047 }
2048
2049 pub fn read_u2(&mut self) -> Result<u16, ClassReadError> {
2050 let bytes = self.read_bytes(2)?;
2051 Ok(u16::from_be_bytes([bytes[0], bytes[1]]))
2052 }
2053
2054 pub fn read_i2(&mut self) -> Result<i16, ClassReadError> {
2055 Ok(self.read_u2()? as i16)
2056 }
2057
2058 pub fn read_u4(&mut self) -> Result<u32, ClassReadError> {
2059 let bytes = self.read_bytes(4)?;
2060 Ok(u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
2061 }
2062
2063 pub fn read_i4(&mut self) -> Result<i32, ClassReadError> {
2064 let bytes = self.read_bytes(4)?;
2065 Ok(i32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
2066 }
2067
2068 pub fn read_u8(&mut self) -> Result<u64, ClassReadError> {
2069 let bytes = self.read_bytes(8)?;
2070 Ok(u64::from_be_bytes([
2071 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
2072 ]))
2073 }
2074
2075 pub fn read_bytes(&mut self, len: usize) -> Result<Vec<u8>, ClassReadError> {
2076 if self.pos + len > self.data.len() {
2077 return Err(ClassReadError::UnexpectedEof);
2078 }
2079 let bytes = self.data[self.pos..self.pos + len].to_vec();
2080 self.pos += len;
2081 Ok(bytes)
2082 }
2083}
2084
2085#[cfg(test)]
2086mod tests {
2087 use crate::constants::*;
2088
2089 use super::*;
2090 use std::cell::RefCell;
2091 use std::rc::Rc;
2092
2093 struct MockClassVisitor {
2095 pub visited_name: Rc<RefCell<Option<String>>>,
2096 pub visited_methods: Rc<RefCell<Vec<String>>>,
2097 }
2098
2099 impl MockClassVisitor {
2100 fn new() -> Self {
2101 Self {
2102 visited_name: Rc::new(RefCell::new(None)),
2103 visited_methods: Rc::new(RefCell::new(Vec::new())),
2104 }
2105 }
2106 }
2107
2108 impl ClassVisitor for MockClassVisitor {
2109 fn visit(
2110 &mut self,
2111 _major: u16,
2112 _minor: u16,
2113 _access_flags: u16,
2114 name: &str,
2115 _super_name: Option<&str>,
2116 _interfaces: &[String],
2117 ) {
2118 *self.visited_name.borrow_mut() = Some(name.to_string());
2119 }
2120
2121 fn visit_method(
2122 &mut self,
2123 _access_flags: u16,
2124 name: &str,
2125 _descriptor: &str,
2126 ) -> Option<Box<dyn MethodVisitor>> {
2127 self.visited_methods.borrow_mut().push(name.to_string());
2128 None
2129 }
2130 }
2131
2132 fn generate_minimal_class() -> Vec<u8> {
2135 let mut w = Vec::new();
2136 w.extend_from_slice(&0xCAFEBABE_u32.to_be_bytes());
2138 w.extend_from_slice(&0_u16.to_be_bytes()); w.extend_from_slice(&52_u16.to_be_bytes()); w.extend_from_slice(&5_u16.to_be_bytes()); w.push(1);
2151 let name = "TestClass";
2152 w.extend_from_slice(&(name.len() as u16).to_be_bytes());
2153 w.extend_from_slice(name.as_bytes());
2154
2155 w.push(7);
2157 w.extend_from_slice(&1_u16.to_be_bytes());
2158
2159 w.push(1);
2161 let obj = "java/lang/Object";
2162 w.extend_from_slice(&(obj.len() as u16).to_be_bytes());
2163 w.extend_from_slice(obj.as_bytes());
2164
2165 w.push(7);
2167 w.extend_from_slice(&3_u16.to_be_bytes());
2168
2169 w.extend_from_slice(&0x0021_u16.to_be_bytes());
2171 w.extend_from_slice(&2_u16.to_be_bytes());
2173 w.extend_from_slice(&4_u16.to_be_bytes());
2175
2176 w.extend_from_slice(&0_u16.to_be_bytes());
2178 w.extend_from_slice(&0_u16.to_be_bytes());
2180 w.extend_from_slice(&0_u16.to_be_bytes());
2182 w.extend_from_slice(&0_u16.to_be_bytes());
2184
2185 w
2186 }
2187
2188 #[test]
2189 fn test_class_reader_header() {
2190 let bytes = generate_minimal_class();
2191 let reader = ClassReader::new(&bytes);
2192 let mut visitor = MockClassVisitor::new();
2193
2194 let result = reader.accept(&mut visitor, 0);
2195
2196 assert!(result.is_ok(), "Should parse valid class file");
2197 assert_eq!(
2198 *visitor.visited_name.borrow(),
2199 Some("TestClass".to_string())
2200 );
2201 }
2202
2203 #[test]
2204 fn test_invalid_magic() {
2205 let bytes = vec![0x00, 0x00, 0x00, 0x00];
2207 let reader = ClassReader::new(&bytes);
2208 let mut visitor = MockClassVisitor::new();
2209
2210 let result = reader.accept(&mut visitor, 0);
2211 assert!(matches!(result, Err(ClassReadError::InvalidMagic(_))));
2212 }
2213
2214 #[test]
2215 fn test_code_reader_alignment() {
2216 let data = vec![0x00, 0x00, 0x00, 0x00]; let mut reader = super::ByteReader::new(&data);
2219
2220 reader.pos = 1;
2222 assert!(reader.align4(0).is_ok());
2224 assert_eq!(reader.pos(), 4);
2225 }
2226
2227 #[test]
2228 fn test_parse_runtime_visible_type_annotations_supertype() {
2229 let mut info = vec![];
2239 u2(1, &mut info);
2240 u1(TA_TARGET_CLASS_EXTENDS, &mut info);
2241 u2(5, &mut info);
2242 u1(0, &mut info);
2243 u2(10, &mut info);
2244 u2(0, &mut info);
2245
2246 let cp: Vec<CpInfo> = vec![];
2247 let attr = parse_attribute("RuntimeVisibleTypeAnnotations", info, &cp).unwrap();
2248
2249 match attr {
2250 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations } => {
2251 assert_eq!(annotations.len(), 1);
2252 let a = &annotations[0];
2253 assert_eq!(a.target_type, TA_TARGET_CLASS_EXTENDS);
2254 assert!(matches!(
2255 a.target_info,
2256 TypeAnnotationTargetInfo::Supertype { supertype_index: 5 }
2257 ));
2258 assert_eq!(a.target_path.path.len(), 0);
2259 assert_eq!(a.annotation.type_descriptor_index, 10);
2260 assert_eq!(a.annotation.element_value_pairs.len(), 0);
2261 }
2262 other => panic!("unexpected attr: {:?}", other),
2263 }
2264 }
2265
2266 #[test]
2267 fn test_parse_runtime_visible_type_annotations_formal_parameter_with_path() {
2268 let mut info = vec![];
2273 u2(1, &mut info);
2274 u1(TA_TARGET_METHOD_FORMAL_PARAMETER, &mut info);
2275 u1(2, &mut info);
2276
2277 u1(1, &mut info); u1(TA_TYPE_PATH_ARRAY, &mut info);
2279 u1(0, &mut info);
2280
2281 u2(9, &mut info);
2282 u2(0, &mut info);
2283
2284 let cp: Vec<CpInfo> = vec![];
2285 let attr = parse_attribute("RuntimeVisibleTypeAnnotations", info, &cp).unwrap();
2286
2287 match attr {
2288 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations } => {
2289 let a = &annotations[0];
2290 assert_eq!(a.target_type, TA_TARGET_METHOD_FORMAL_PARAMETER);
2291 assert!(matches!(
2292 a.target_info,
2293 TypeAnnotationTargetInfo::FormalParameter {
2294 formal_parameter_index: 2
2295 }
2296 ));
2297 assert_eq!(a.target_path.path.len(), 1);
2298 assert_eq!(a.target_path.path[0].type_path_kind, TA_TYPE_PATH_ARRAY);
2299 assert_eq!(a.target_path.path[0].type_argument_index, 0);
2300 }
2301 other => panic!("unexpected attr: {:?}", other),
2302 }
2303 }
2304
2305 #[test]
2306 fn test_parse_runtime_visible_type_annotations_localvar_table() {
2307 let mut info = vec![];
2313 u2(1, &mut info);
2314 u1(TA_TARGET_LOCAL_VARIABLE, &mut info);
2315
2316 u2(1, &mut info); u2(1, &mut info);
2318 u2(2, &mut info);
2319 u2(3, &mut info);
2320
2321 u1(0, &mut info); u2(8, &mut info);
2323 u2(0, &mut info);
2324
2325 let cp: Vec<CpInfo> = vec![];
2326 let attr = parse_attribute("RuntimeVisibleTypeAnnotations", info, &cp).unwrap();
2327
2328 match attr {
2329 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations } => {
2330 let a = &annotations[0];
2331 assert_eq!(a.target_type, TA_TARGET_LOCAL_VARIABLE);
2332 match &a.target_info {
2333 TypeAnnotationTargetInfo::LocalVar { table } => {
2334 assert_eq!(table.len(), 1);
2335 assert_eq!(table[0].start_pc, 1);
2336 assert_eq!(table[0].length, 2);
2337 assert_eq!(table[0].index, 3);
2338 }
2339 other => panic!("unexpected target_info: {:?}", other),
2340 }
2341 }
2342 other => panic!("unexpected attr: {:?}", other),
2343 }
2344 }
2345
2346 fn u1(v: u8, out: &mut Vec<u8>) {
2347 out.push(v);
2348 }
2349 fn u2(v: u16, out: &mut Vec<u8>) {
2350 out.extend_from_slice(&v.to_be_bytes());
2351 }
2352
2353 #[test]
2354 fn test_parse_runtime_visible_annotations_one_empty() {
2355 let mut info = vec![];
2358 u2(1, &mut info);
2359 u2(10, &mut info);
2360 u2(0, &mut info);
2361
2362 let cp: Vec<CpInfo> = vec![];
2363 let attr = parse_attribute("RuntimeVisibleAnnotations", info, &cp).unwrap();
2364 match attr {
2365 AttributeInfo::RuntimeVisibleAnnotations { annotations } => {
2366 assert_eq!(annotations.len(), 1);
2367 assert_eq!(annotations[0].type_descriptor_index, 10);
2368 assert_eq!(annotations[0].element_value_pairs.len(), 0);
2369 }
2370 other => panic!("unexpected attr: {:?}", other),
2371 }
2372 }
2373
2374 #[test]
2375 fn test_parse_runtime_visible_parameter_annotations_two_params() {
2376 let mut info = vec![];
2380 u1(2, &mut info);
2381 u2(1, &mut info);
2382 u2(10, &mut info);
2383 u2(0, &mut info);
2384 u2(0, &mut info);
2385
2386 let cp: Vec<CpInfo> = vec![];
2387 let attr = parse_attribute("RuntimeVisibleParameterAnnotations", info, &cp).unwrap();
2388 match attr {
2389 AttributeInfo::RuntimeVisibleParameterAnnotations { parameters } => {
2390 assert_eq!(parameters.parameters.len(), 2);
2391 assert_eq!(parameters.parameters[0].len(), 1);
2392 assert_eq!(parameters.parameters[1].len(), 0);
2393 }
2394 other => panic!("unexpected attr: {:?}", other),
2395 }
2396 }
2397}