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 LineNumberInsnNode, LookupSwitchInsnNode, MemberRef, MethodInsnNode, MultiANewArrayInsnNode,
7 TableSwitchInsnNode, 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 ModuleVisitor {
113 fn visit_main_class(&mut self, _main_class: &str) {}
114 fn visit_package(&mut self, _package: &str) {}
115 fn visit_require(&mut self, _module: &str, _access_flags: u16, _version: Option<&str>) {}
116 fn visit_export(&mut self, _package: &str, _access_flags: u16, _modules: &[String]) {}
117 fn visit_open(&mut self, _package: &str, _access_flags: u16, _modules: &[String]) {}
118 fn visit_use(&mut self, _service: &str) {}
119 fn visit_provide(&mut self, _service: &str, _providers: &[String]) {}
120 fn visit_end(&mut self) {}
121}
122
123pub trait ClassVisitor {
128 fn visit(
139 &mut self,
140 _major: u16,
141 _minor: u16,
142 _access_flags: u16,
143 _name: &str,
144 _super_name: Option<&str>,
145 _interfaces: &[String],
146 ) {
147 }
148
149 fn visit_source(&mut self, _source: &str) {}
151
152 fn visit_module(
154 &mut self,
155 _name: &str,
156 _access_flags: u16,
157 _version: Option<&str>,
158 ) -> Option<Box<dyn ModuleVisitor>> {
159 None
160 }
161
162 fn visit_field(
166 &mut self,
167 _access_flags: u16,
168 _name: &str,
169 _descriptor: &str,
170 ) -> Option<Box<dyn FieldVisitor>> {
171 None
172 }
173
174 fn visit_method(
178 &mut self,
179 _access_flags: u16,
180 _name: &str,
181 _descriptor: &str,
182 ) -> Option<Box<dyn MethodVisitor>> {
183 None
184 }
185
186 fn visit_end(&mut self) {}
188}
189
190pub struct ClassReader {
196 bytes: Vec<u8>,
197}
198
199impl ClassReader {
200 pub fn new(bytes: &[u8]) -> Self {
206 Self {
207 bytes: bytes.to_vec(),
208 }
209 }
210
211 pub fn accept(
224 &self,
225 visitor: &mut dyn ClassVisitor,
226 _options: u32,
227 ) -> Result<(), ClassReadError> {
228 let class_file = read_class_file(&self.bytes)?;
229 let name = class_file.class_name(class_file.this_class)?.to_string();
230 let super_name = if class_file.super_class == 0 {
231 None
232 } else {
233 Some(class_file.class_name(class_file.super_class)?.to_string())
234 };
235 let mut interfaces = Vec::with_capacity(class_file.interfaces.len());
236 for index in &class_file.interfaces {
237 interfaces.push(class_file.class_name(*index)?.to_string());
238 }
239
240 visitor.visit(
241 class_file.major_version,
242 class_file.minor_version,
243 class_file.access_flags,
244 &name,
245 super_name.as_deref(),
246 &interfaces,
247 );
248
249 for attr in &class_file.attributes {
250 if let AttributeInfo::SourceFile { sourcefile_index } = attr {
251 let source = class_file.cp_utf8(*sourcefile_index)?;
252 visitor.visit_source(source);
253 }
254 }
255
256 if let Some(module_attr) = class_file.attributes.iter().find_map(|attr| match attr {
257 AttributeInfo::Module(module) => Some(module),
258 _ => None,
259 }) {
260 let version = if module_attr.module_version_index == 0 {
261 None
262 } else {
263 Some(class_file.cp_utf8(module_attr.module_version_index)?)
264 };
265 if let Some(mut mv) = visitor.visit_module(
266 class_file.module_name(module_attr.module_name_index)?,
267 module_attr.module_flags,
268 version,
269 ) {
270 if let Some(main_class_index) =
271 class_file.attributes.iter().find_map(|attr| match attr {
272 AttributeInfo::ModuleMainClass { main_class_index } => {
273 Some(*main_class_index)
274 }
275 _ => None,
276 })
277 {
278 mv.visit_main_class(class_file.class_name(main_class_index)?);
279 }
280 if let Some(package_index_table) =
281 class_file.attributes.iter().find_map(|attr| match attr {
282 AttributeInfo::ModulePackages {
283 package_index_table,
284 } => Some(package_index_table.as_slice()),
285 _ => None,
286 })
287 {
288 for package_index in package_index_table {
289 mv.visit_package(class_file.package_name(*package_index)?);
290 }
291 }
292 for require in &module_attr.requires {
293 let version = if require.requires_version_index == 0 {
294 None
295 } else {
296 Some(class_file.cp_utf8(require.requires_version_index)?)
297 };
298 mv.visit_require(
299 class_file.module_name(require.requires_index)?,
300 require.requires_flags,
301 version,
302 );
303 }
304 for export in &module_attr.exports {
305 let modules = export
306 .exports_to_index
307 .iter()
308 .map(|index| class_file.module_name(*index).map(str::to_string))
309 .collect::<Result<Vec<_>, _>>()?;
310 mv.visit_export(
311 class_file.package_name(export.exports_index)?,
312 export.exports_flags,
313 &modules,
314 );
315 }
316 for open in &module_attr.opens {
317 let modules = open
318 .opens_to_index
319 .iter()
320 .map(|index| class_file.module_name(*index).map(str::to_string))
321 .collect::<Result<Vec<_>, _>>()?;
322 mv.visit_open(
323 class_file.package_name(open.opens_index)?,
324 open.opens_flags,
325 &modules,
326 );
327 }
328 for uses_index in &module_attr.uses_index {
329 mv.visit_use(class_file.class_name(*uses_index)?);
330 }
331 for provide in &module_attr.provides {
332 let providers = provide
333 .provides_with_index
334 .iter()
335 .map(|index| class_file.class_name(*index).map(str::to_string))
336 .collect::<Result<Vec<_>, _>>()?;
337 mv.visit_provide(class_file.class_name(provide.provides_index)?, &providers);
338 }
339 mv.visit_end();
340 }
341 }
342
343 for field in &class_file.fields {
344 let field_name = class_file.cp_utf8(field.name_index)?;
345 let field_desc = class_file.cp_utf8(field.descriptor_index)?;
346 if let Some(mut fv) = visitor.visit_field(field.access_flags, field_name, field_desc) {
347 fv.visit_end();
348 }
349 }
350
351 for method in &class_file.methods {
352 let method_name = class_file.cp_utf8(method.name_index)?;
353 let method_desc = class_file.cp_utf8(method.descriptor_index)?;
354 if let Some(mut mv) =
355 visitor.visit_method(method.access_flags, method_name, method_desc)
356 {
357 let code = method.attributes.iter().find_map(|attr| match attr {
358 AttributeInfo::Code(code) => Some(code),
359 _ => None,
360 });
361 if let Some(code) = code {
362 mv.visit_code();
363 let instructions = parse_code_instructions_with_offsets(&code.code)?;
364 for instruction in instructions {
365 visit_instruction(
366 &class_file.constant_pool,
367 instruction.offset as i32,
368 instruction.insn,
369 &mut *mv,
370 )?;
371 }
372 mv.visit_maxs(code.max_stack, code.max_locals);
373 }
374 mv.visit_end();
375 }
376 }
377
378 visitor.visit_end();
379 Ok(())
380 }
381
382 pub fn to_class_node(&self) -> Result<crate::nodes::ClassNode, ClassReadError> {
387 let class_file = read_class_file(&self.bytes)?;
388 class_file.to_class_node()
389 }
390}
391
392#[derive(Debug, Clone)]
393pub struct ClassFile {
394 pub minor_version: u16,
395 pub major_version: u16,
396 pub constant_pool: Vec<CpInfo>,
397 pub access_flags: u16,
398 pub this_class: u16,
399 pub super_class: u16,
400 pub interfaces: Vec<u16>,
401 pub fields: Vec<FieldInfo>,
402 pub methods: Vec<MethodInfo>,
403 pub attributes: Vec<AttributeInfo>,
404}
405
406impl ClassFile {
407 pub fn cp_utf8(&self, index: u16) -> Result<&str, ClassReadError> {
408 match self
409 .constant_pool
410 .get(index as usize)
411 .ok_or(ClassReadError::InvalidIndex(index))?
412 {
413 CpInfo::Utf8(value) => Ok(value.as_str()),
414 _ => Err(ClassReadError::InvalidIndex(index)),
415 }
416 }
417
418 pub fn class_name(&self, index: u16) -> Result<&str, ClassReadError> {
419 match self
420 .constant_pool
421 .get(index as usize)
422 .ok_or(ClassReadError::InvalidIndex(index))?
423 {
424 CpInfo::Class { name_index } => self.cp_utf8(*name_index),
425 _ => Err(ClassReadError::InvalidIndex(index)),
426 }
427 }
428
429 pub fn module_name(&self, index: u16) -> Result<&str, ClassReadError> {
430 match self
431 .constant_pool
432 .get(index as usize)
433 .ok_or(ClassReadError::InvalidIndex(index))?
434 {
435 CpInfo::Module { name_index } => self.cp_utf8(*name_index),
436 _ => Err(ClassReadError::InvalidIndex(index)),
437 }
438 }
439
440 pub fn package_name(&self, index: u16) -> Result<&str, ClassReadError> {
441 match self
442 .constant_pool
443 .get(index as usize)
444 .ok_or(ClassReadError::InvalidIndex(index))?
445 {
446 CpInfo::Package { name_index } => self.cp_utf8(*name_index),
447 _ => Err(ClassReadError::InvalidIndex(index)),
448 }
449 }
450
451 pub fn to_class_node(&self) -> Result<crate::nodes::ClassNode, ClassReadError> {
452 let name = self.class_name(self.this_class)?.to_string();
453 let super_name = if self.super_class == 0 {
454 None
455 } else {
456 Some(self.class_name(self.super_class)?.to_string())
457 };
458 let source_file = self.attributes.iter().find_map(|attr| match attr {
459 AttributeInfo::SourceFile { sourcefile_index } => self
460 .cp_utf8(*sourcefile_index)
461 .ok()
462 .map(|value| value.to_string()),
463 _ => None,
464 });
465 let mut interfaces = Vec::with_capacity(self.interfaces.len());
466 for index in &self.interfaces {
467 interfaces.push(self.class_name(*index)?.to_string());
468 }
469
470 let mut fields = Vec::with_capacity(self.fields.len());
471 for field in &self.fields {
472 let name = self.cp_utf8(field.name_index)?.to_string();
473 let descriptor = self.cp_utf8(field.descriptor_index)?.to_string();
474 fields.push(crate::nodes::FieldNode {
475 access_flags: field.access_flags,
476 name,
477 descriptor,
478 attributes: field.attributes.clone(),
479 });
480 }
481
482 let mut methods = Vec::with_capacity(self.methods.len());
483 for method in &self.methods {
484 let name = self.cp_utf8(method.name_index)?.to_string();
485 let descriptor = self.cp_utf8(method.descriptor_index)?.to_string();
486 let mut method_attributes = method.attributes.clone();
487 method_attributes.retain(|attr| !matches!(attr, AttributeInfo::Code(_)));
488 let code = method.attributes.iter().find_map(|attr| match attr {
489 AttributeInfo::Code(code) => Some(code),
490 _ => None,
491 });
492
493 let (
494 has_code,
495 max_stack,
496 max_locals,
497 instructions,
498 instruction_offsets,
499 insn_nodes,
500 exception_table,
501 try_catch_blocks,
502 line_numbers,
503 local_variables,
504 code_attributes,
505 ) = if let Some(code) = code {
506 let mut list = InsnList::new();
507 let mut instruction_offsets = Vec::with_capacity(code.instructions.len());
508 for insn in &code.instructions {
509 list.add(insn.clone());
510 }
511 for node in parse_code_instructions_with_offsets(&code.code)? {
512 instruction_offsets.push(node.offset);
513 }
514 let line_numbers = code
515 .attributes
516 .iter()
517 .find_map(|attr| match attr {
518 AttributeInfo::LineNumberTable { entries } => Some(entries.clone()),
519 _ => None,
520 })
521 .unwrap_or_default();
522 let local_variables = code
523 .attributes
524 .iter()
525 .find_map(|attr| match attr {
526 AttributeInfo::LocalVariableTable { entries } => Some(entries.clone()),
527 _ => None,
528 })
529 .unwrap_or_default();
530 (
531 true,
532 code.max_stack,
533 code.max_locals,
534 list,
535 instruction_offsets,
536 code.insn_nodes.clone(),
537 code.exception_table.clone(),
538 code.try_catch_blocks.clone(),
539 line_numbers,
540 local_variables,
541 code.attributes.clone(),
542 )
543 } else {
544 (
545 false,
546 0,
547 0,
548 InsnList::new(),
549 Vec::new(),
550 Vec::new(),
551 Vec::new(),
552 Vec::new(),
553 Vec::new(),
554 Vec::new(),
555 Vec::new(),
556 )
557 };
558 let method_parameters = method
559 .attributes
560 .iter()
561 .find_map(|attr| match attr {
562 AttributeInfo::MethodParameters { parameters } => Some(parameters.clone()),
563 _ => None,
564 })
565 .unwrap_or_default();
566 let exceptions = method
567 .attributes
568 .iter()
569 .find_map(|attr| match attr {
570 AttributeInfo::Exceptions {
571 exception_index_table,
572 } => Some(exception_index_table),
573 _ => None,
574 })
575 .map(|entries| -> Result<Vec<String>, ClassReadError> {
576 let mut values = Vec::with_capacity(entries.len());
577 for index in entries {
578 values.push(self.class_name(*index)?.to_string());
579 }
580 Ok(values)
581 })
582 .transpose()?
583 .unwrap_or_default();
584 let signature = method.attributes.iter().find_map(|attr| match attr {
585 AttributeInfo::Signature { signature_index } => self
586 .cp_utf8(*signature_index)
587 .ok()
588 .map(|value| value.to_string()),
589 _ => None,
590 });
591
592 methods.push(crate::nodes::MethodNode {
593 access_flags: method.access_flags,
594 name,
595 descriptor,
596 has_code,
597 max_stack,
598 max_locals,
599 instructions,
600 instruction_offsets,
601 insn_nodes,
602 exception_table,
603 try_catch_blocks,
604 line_numbers,
605 local_variables,
606 method_parameters,
607 exceptions,
608 signature,
609 code_attributes,
610 attributes: method_attributes,
611 });
612 }
613
614 let mut inner_classes = Vec::new();
615 for attr in &self.attributes {
616 if let AttributeInfo::InnerClasses { classes } = attr {
617 for entry in classes {
618 let name = self.class_name(entry.inner_class_info_index)?.to_string();
619 let outer_name = if entry.outer_class_info_index == 0 {
620 None
621 } else {
622 Some(self.class_name(entry.outer_class_info_index)?.to_string())
623 };
624 let inner_name = if entry.inner_name_index == 0 {
625 None
626 } else {
627 Some(self.cp_utf8(entry.inner_name_index)?.to_string())
628 };
629 inner_classes.push(crate::nodes::InnerClassNode {
630 name,
631 outer_name,
632 inner_name,
633 access_flags: entry.inner_class_access_flags,
634 });
635 }
636 }
637 }
638
639 let mut outer_class = String::new();
640 if let Some(class_index) = self.attributes.iter().find_map(|attr| match attr {
641 AttributeInfo::EnclosingMethod { class_index, .. } => Some(*class_index),
642 _ => None,
643 }) {
644 outer_class = self.class_name(class_index)?.to_string();
645 }
646 if outer_class.is_empty() {
647 for attr in &self.attributes {
648 if let AttributeInfo::InnerClasses { classes } = attr
649 && let Some(entry) = classes.iter().find(|entry| {
650 entry.inner_class_info_index == self.this_class
651 && entry.outer_class_info_index != 0
652 })
653 {
654 outer_class = self.class_name(entry.outer_class_info_index)?.to_string();
655 break;
656 }
657 }
658 }
659
660 let module = self
661 .attributes
662 .iter()
663 .find_map(|attr| match attr {
664 AttributeInfo::Module(module) => Some(module),
665 _ => None,
666 })
667 .map(|module| {
668 let requires = module
669 .requires
670 .iter()
671 .map(|require| {
672 Ok(crate::nodes::ModuleRequireNode {
673 module: self.module_name(require.requires_index)?.to_string(),
674 access_flags: require.requires_flags,
675 version: if require.requires_version_index == 0 {
676 None
677 } else {
678 Some(self.cp_utf8(require.requires_version_index)?.to_string())
679 },
680 })
681 })
682 .collect::<Result<Vec<_>, ClassReadError>>()?;
683 let exports = module
684 .exports
685 .iter()
686 .map(|export| {
687 Ok(crate::nodes::ModuleExportNode {
688 package: self.package_name(export.exports_index)?.to_string(),
689 access_flags: export.exports_flags,
690 modules: export
691 .exports_to_index
692 .iter()
693 .map(|index| self.module_name(*index).map(str::to_string))
694 .collect::<Result<Vec<_>, ClassReadError>>()?,
695 })
696 })
697 .collect::<Result<Vec<_>, ClassReadError>>()?;
698 let opens = module
699 .opens
700 .iter()
701 .map(|open| {
702 Ok(crate::nodes::ModuleOpenNode {
703 package: self.package_name(open.opens_index)?.to_string(),
704 access_flags: open.opens_flags,
705 modules: open
706 .opens_to_index
707 .iter()
708 .map(|index| self.module_name(*index).map(str::to_string))
709 .collect::<Result<Vec<_>, ClassReadError>>()?,
710 })
711 })
712 .collect::<Result<Vec<_>, ClassReadError>>()?;
713 let provides = module
714 .provides
715 .iter()
716 .map(|provide| {
717 Ok(crate::nodes::ModuleProvideNode {
718 service: self.class_name(provide.provides_index)?.to_string(),
719 providers: provide
720 .provides_with_index
721 .iter()
722 .map(|index| self.class_name(*index).map(str::to_string))
723 .collect::<Result<Vec<_>, ClassReadError>>()?,
724 })
725 })
726 .collect::<Result<Vec<_>, ClassReadError>>()?;
727 let packages = self
728 .attributes
729 .iter()
730 .find_map(|attr| match attr {
731 AttributeInfo::ModulePackages {
732 package_index_table,
733 } => Some(package_index_table),
734 _ => None,
735 })
736 .map(|package_index_table| {
737 package_index_table
738 .iter()
739 .map(|index| self.package_name(*index).map(str::to_string))
740 .collect::<Result<Vec<_>, ClassReadError>>()
741 })
742 .transpose()?
743 .unwrap_or_default();
744 let main_class = self
745 .attributes
746 .iter()
747 .find_map(|attr| match attr {
748 AttributeInfo::ModuleMainClass { main_class_index } => {
749 Some(*main_class_index)
750 }
751 _ => None,
752 })
753 .map(|index| self.class_name(index).map(str::to_string))
754 .transpose()?;
755
756 Ok(crate::nodes::ModuleNode {
757 name: self.module_name(module.module_name_index)?.to_string(),
758 access_flags: module.module_flags,
759 version: if module.module_version_index == 0 {
760 None
761 } else {
762 Some(self.cp_utf8(module.module_version_index)?.to_string())
763 },
764 requires,
765 exports,
766 opens,
767 uses: module
768 .uses_index
769 .iter()
770 .map(|index| self.class_name(*index).map(str::to_string))
771 .collect::<Result<Vec<_>, ClassReadError>>()?,
772 provides,
773 packages,
774 main_class,
775 })
776 })
777 .transpose()?;
778
779 let permitted_subclasses = self
780 .attributes
781 .iter()
782 .find_map(|attr| match attr {
783 AttributeInfo::PermittedSubclasses { classes } => Some(classes),
784 _ => None,
785 })
786 .map(|classes| {
787 classes
788 .iter()
789 .map(|index| self.class_name(*index).map(str::to_string))
790 .collect::<Result<Vec<_>, ClassReadError>>()
791 })
792 .transpose()?
793 .unwrap_or_default();
794
795 let record_components = self
796 .attributes
797 .iter()
798 .find_map(|attr| match attr {
799 AttributeInfo::Record { components } => Some(components),
800 _ => None,
801 })
802 .map(|components| {
803 components
804 .iter()
805 .map(|comp| {
806 Ok(crate::nodes::RecordComponentNode {
807 name: self.cp_utf8(comp.name_index)?.to_string(),
808 descriptor: self.cp_utf8(comp.descriptor_index)?.to_string(),
809 attributes: comp.attributes.clone(),
810 })
811 })
812 .collect::<Result<Vec<_>, ClassReadError>>()
813 })
814 .transpose()?
815 .unwrap_or_default();
816
817 Ok(crate::nodes::ClassNode {
818 minor_version: self.minor_version,
819 major_version: self.major_version,
820 access_flags: self.access_flags,
821 constant_pool: self.constant_pool.clone(),
822 this_class: self.this_class,
823 name,
824 super_name,
825 source_file,
826 interfaces,
827 interface_indices: self.interfaces.clone(),
828 fields,
829 methods,
830 attributes: self.attributes.clone(),
831 inner_classes,
832 outer_class,
833 module,
834 record_components,
835 permitted_subclasses,
836 })
837 }
838}
839
840#[derive(Debug, Clone)]
841pub struct FieldInfo {
842 pub access_flags: u16,
843 pub name_index: u16,
844 pub descriptor_index: u16,
845 pub attributes: Vec<AttributeInfo>,
846}
847
848#[derive(Debug, Clone)]
849pub struct MethodInfo {
850 pub access_flags: u16,
851 pub name_index: u16,
852 pub descriptor_index: u16,
853 pub attributes: Vec<AttributeInfo>,
854}
855
856#[derive(Debug, Clone)]
857pub struct RecordComponent {
858 pub name_index: u16,
859 pub descriptor_index: u16,
860 pub attributes: Vec<AttributeInfo>,
861}
862
863#[derive(Debug, Clone)]
864pub enum AttributeInfo {
865 Code(CodeAttribute),
866 ConstantValue { constantvalue_index: u16 },
867 Exceptions { exception_index_table: Vec<u16> },
868 SourceFile { sourcefile_index: u16 },
869 LineNumberTable { entries: Vec<LineNumber> },
870 LocalVariableTable { entries: Vec<LocalVariable> },
871 Signature { signature_index: u16 },
872 StackMapTable { entries: Vec<StackMapFrame> },
873 Deprecated,
874 Synthetic,
875 InnerClasses { classes: Vec<InnerClass> },
876 EnclosingMethod { class_index: u16, method_index: u16 },
877 Module(ModuleAttribute),
878 ModulePackages { package_index_table: Vec<u16> },
879 ModuleMainClass { main_class_index: u16 },
880 BootstrapMethods { methods: Vec<BootstrapMethod> },
881 MethodParameters { parameters: Vec<MethodParameter> },
882 RuntimeVisibleAnnotations { annotations: Vec<Annotation> },
883 RuntimeInvisibleAnnotations { annotations: Vec<Annotation> },
884 RuntimeVisibleParameterAnnotations { parameters: ParameterAnnotations },
885 RuntimeInvisibleParameterAnnotations { parameters: ParameterAnnotations },
886 RuntimeVisibleTypeAnnotations { annotations: Vec<TypeAnnotation> },
887 RuntimeInvisibleTypeAnnotations { annotations: Vec<TypeAnnotation> },
888 PermittedSubclasses { classes: Vec<u16> },
889 Record { components: Vec<RecordComponent> },
890 Unknown { name: String, info: Vec<u8> },
891}
892
893#[derive(Debug, Clone, PartialEq, Eq)]
894pub struct ModuleAttribute {
895 pub module_name_index: u16,
896 pub module_flags: u16,
897 pub module_version_index: u16,
898 pub requires: Vec<ModuleRequire>,
899 pub exports: Vec<ModuleExport>,
900 pub opens: Vec<ModuleOpen>,
901 pub uses_index: Vec<u16>,
902 pub provides: Vec<ModuleProvide>,
903}
904
905#[derive(Debug, Clone, PartialEq, Eq)]
906pub struct ModuleRequire {
907 pub requires_index: u16,
908 pub requires_flags: u16,
909 pub requires_version_index: u16,
910}
911
912#[derive(Debug, Clone, PartialEq, Eq)]
913pub struct ModuleExport {
914 pub exports_index: u16,
915 pub exports_flags: u16,
916 pub exports_to_index: Vec<u16>,
917}
918
919#[derive(Debug, Clone, PartialEq, Eq)]
920pub struct ModuleOpen {
921 pub opens_index: u16,
922 pub opens_flags: u16,
923 pub opens_to_index: Vec<u16>,
924}
925
926#[derive(Debug, Clone, PartialEq, Eq)]
927pub struct ModuleProvide {
928 pub provides_index: u16,
929 pub provides_with_index: Vec<u16>,
930}
931
932#[derive(Debug, Clone, PartialEq)]
933pub struct Annotation {
934 pub type_descriptor_index: u16,
935 pub element_value_pairs: Vec<ElementValuePair>,
936}
937
938#[derive(Debug, Clone, PartialEq)]
939pub struct ElementValuePair {
940 pub element_name_index: u16,
941 pub value: ElementValue,
942}
943
944#[derive(Debug, Clone, PartialEq)]
945pub enum ElementValue {
946 ConstValueIndex {
947 tag: u8,
948 const_value_index: u16,
949 },
950 EnumConstValue {
951 type_name_index: u16,
952 const_name_index: u16,
953 },
954 ClassInfoIndex {
955 class_info_index: u16,
956 },
957 AnnotationValue(Box<Annotation>),
958 ArrayValue(Vec<ElementValue>),
959}
960
961#[derive(Debug, Clone, PartialEq)]
962pub struct ParameterAnnotations {
963 pub parameters: Vec<Vec<Annotation>>,
964}
965
966#[derive(Debug, Clone, PartialEq)]
967pub struct TypeAnnotation {
968 pub target_type: u8,
969 pub target_info: TypeAnnotationTargetInfo,
970 pub target_path: TypePath,
971 pub annotation: Annotation,
972}
973
974#[derive(Debug, Clone, PartialEq)]
975pub struct TypePath {
976 pub path: Vec<TypePathEntry>,
977}
978
979#[derive(Debug, Clone, PartialEq)]
980pub struct TypePathEntry {
981 pub type_path_kind: u8,
982 pub type_argument_index: u8,
983}
984
985#[derive(Debug, Clone, PartialEq)]
986pub enum TypeAnnotationTargetInfo {
987 TypeParameter {
988 type_parameter_index: u8,
989 },
990 Supertype {
991 supertype_index: u16,
992 },
993 TypeParameterBound {
994 type_parameter_index: u8,
995 bound_index: u8,
996 },
997 Empty,
998 FormalParameter {
999 formal_parameter_index: u8,
1000 },
1001 Throws {
1002 throws_type_index: u16,
1003 },
1004 LocalVar {
1005 table: Vec<LocalVarTargetTableEntry>,
1006 },
1007 Catch {
1008 exception_table_index: u16,
1009 },
1010 Offset {
1011 offset: u16,
1012 },
1013 TypeArgument {
1014 offset: u16,
1015 type_argument_index: u8,
1016 },
1017}
1018
1019#[derive(Debug, Clone, PartialEq)]
1020pub struct LocalVarTargetTableEntry {
1021 pub start_pc: u16,
1022 pub length: u16,
1023 pub index: u16,
1024}
1025
1026#[derive(Debug, Clone)]
1027pub struct CodeAttribute {
1028 pub max_stack: u16,
1029 pub max_locals: u16,
1030 pub code: Vec<u8>,
1031 pub instructions: Vec<Insn>,
1032 pub insn_nodes: Vec<AbstractInsnNode>,
1033 pub exception_table: Vec<ExceptionTableEntry>,
1034 pub try_catch_blocks: Vec<TryCatchBlockNode>,
1035 pub attributes: Vec<AttributeInfo>,
1036}
1037
1038#[derive(Debug, Clone)]
1039pub struct ExceptionTableEntry {
1040 pub start_pc: u16,
1041 pub end_pc: u16,
1042 pub handler_pc: u16,
1043 pub catch_type: u16,
1044}
1045
1046#[derive(Debug, Clone)]
1047pub struct LineNumber {
1048 pub start_pc: u16,
1049 pub line_number: u16,
1050}
1051
1052#[derive(Debug, Clone)]
1053pub struct LocalVariable {
1054 pub start_pc: u16,
1055 pub length: u16,
1056 pub name_index: u16,
1057 pub descriptor_index: u16,
1058 pub index: u16,
1059}
1060
1061#[derive(Debug, Clone)]
1062pub struct InnerClass {
1063 pub inner_class_info_index: u16,
1064 pub outer_class_info_index: u16,
1065 pub inner_name_index: u16,
1066 pub inner_class_access_flags: u16,
1067}
1068
1069#[derive(Debug, Clone)]
1070pub struct BootstrapMethod {
1071 pub bootstrap_method_ref: u16,
1072 pub bootstrap_arguments: Vec<u16>,
1073}
1074
1075#[derive(Debug, Clone)]
1076pub struct MethodParameter {
1077 pub name_index: u16,
1078 pub access_flags: u16,
1079}
1080
1081#[derive(Debug, Clone, PartialEq, Eq)]
1082pub enum VerificationTypeInfo {
1083 Top,
1084 Integer,
1085 Float,
1086 Long,
1087 Double,
1088 Null,
1089 UninitializedThis,
1090 Object { cpool_index: u16 },
1091 Uninitialized { offset: u16 },
1092}
1093
1094#[derive(Debug, Clone)]
1095pub enum StackMapFrame {
1096 SameFrame {
1097 offset_delta: u16,
1098 },
1099 SameLocals1StackItemFrame {
1100 offset_delta: u16,
1101 stack: VerificationTypeInfo,
1102 },
1103 SameLocals1StackItemFrameExtended {
1104 offset_delta: u16,
1105 stack: VerificationTypeInfo,
1106 },
1107 ChopFrame {
1108 offset_delta: u16,
1109 k: u8,
1110 },
1111 SameFrameExtended {
1112 offset_delta: u16,
1113 },
1114 AppendFrame {
1115 offset_delta: u16,
1116 locals: Vec<VerificationTypeInfo>,
1117 },
1118 FullFrame {
1119 offset_delta: u16,
1120 locals: Vec<VerificationTypeInfo>,
1121 stack: Vec<VerificationTypeInfo>,
1122 },
1123}
1124
1125pub fn read_class_file(bytes: &[u8]) -> Result<ClassFile, ClassReadError> {
1126 let mut reader = ByteReader::new(bytes);
1127 let magic = reader.read_u4()?;
1128 if magic != 0xCAFEBABE {
1129 return Err(ClassReadError::InvalidMagic(magic));
1130 }
1131 let minor_version = reader.read_u2()?;
1132 let major_version = reader.read_u2()?;
1133 if major_version > constants::V25 {
1134 return Err(ClassReadError::InvalidClassVersion(major_version));
1135 }
1136 let constant_pool = read_constant_pool(&mut reader)?;
1137 let access_flags = reader.read_u2()?;
1138 let this_class = reader.read_u2()?;
1139 let super_class = reader.read_u2()?;
1140 let interfaces = read_u2_table(&mut reader)?;
1141 let fields = read_fields(&mut reader, &constant_pool)?;
1142 let methods = read_methods(&mut reader, &constant_pool)?;
1143 let attributes = read_attributes(&mut reader, &constant_pool)?;
1144
1145 Ok(ClassFile {
1146 minor_version,
1147 major_version,
1148 constant_pool,
1149 access_flags,
1150 this_class,
1151 super_class,
1152 interfaces,
1153 fields,
1154 methods,
1155 attributes,
1156 })
1157}
1158
1159fn read_constant_pool(reader: &mut ByteReader<'_>) -> Result<Vec<CpInfo>, ClassReadError> {
1160 let count = reader.read_u2()? as usize;
1161 let mut pool = Vec::with_capacity(count);
1162 pool.push(CpInfo::Unusable);
1163
1164 let mut index = 1;
1165 while index < count {
1166 let tag = reader.read_u1()?;
1167 let entry = match tag {
1168 1 => {
1169 let len = reader.read_u2()? as usize;
1170 let bytes = reader.read_bytes(len)?;
1171 let value = decode_modified_utf8(&bytes)?;
1172 CpInfo::Utf8(value)
1173 }
1174 3 => {
1175 let value = reader.read_u4()? as i32;
1176 CpInfo::Integer(value)
1177 }
1178 4 => {
1179 let value = f32::from_bits(reader.read_u4()?);
1180 CpInfo::Float(value)
1181 }
1182 5 => {
1183 let value = reader.read_u8()? as i64;
1184 CpInfo::Long(value)
1185 }
1186 6 => {
1187 let value = f64::from_bits(reader.read_u8()?);
1188 CpInfo::Double(value)
1189 }
1190 7 => CpInfo::Class {
1191 name_index: reader.read_u2()?,
1192 },
1193 8 => CpInfo::String {
1194 string_index: reader.read_u2()?,
1195 },
1196 9 => CpInfo::Fieldref {
1197 class_index: reader.read_u2()?,
1198 name_and_type_index: reader.read_u2()?,
1199 },
1200 10 => CpInfo::Methodref {
1201 class_index: reader.read_u2()?,
1202 name_and_type_index: reader.read_u2()?,
1203 },
1204 11 => CpInfo::InterfaceMethodref {
1205 class_index: reader.read_u2()?,
1206 name_and_type_index: reader.read_u2()?,
1207 },
1208 12 => CpInfo::NameAndType {
1209 name_index: reader.read_u2()?,
1210 descriptor_index: reader.read_u2()?,
1211 },
1212 15 => CpInfo::MethodHandle {
1213 reference_kind: reader.read_u1()?,
1214 reference_index: reader.read_u2()?,
1215 },
1216 16 => CpInfo::MethodType {
1217 descriptor_index: reader.read_u2()?,
1218 },
1219 17 => CpInfo::Dynamic {
1220 bootstrap_method_attr_index: reader.read_u2()?,
1221 name_and_type_index: reader.read_u2()?,
1222 },
1223 18 => CpInfo::InvokeDynamic {
1224 bootstrap_method_attr_index: reader.read_u2()?,
1225 name_and_type_index: reader.read_u2()?,
1226 },
1227 19 => CpInfo::Module {
1228 name_index: reader.read_u2()?,
1229 },
1230 20 => CpInfo::Package {
1231 name_index: reader.read_u2()?,
1232 },
1233 _ => return Err(ClassReadError::InvalidConstantPoolTag(tag)),
1234 };
1235
1236 pool.push(entry);
1237
1238 if tag == 5 || tag == 6 {
1239 pool.push(CpInfo::Unusable);
1240 index += 2;
1241 } else {
1242 index += 1;
1243 }
1244 }
1245
1246 Ok(pool)
1247}
1248
1249fn read_u2_table(reader: &mut ByteReader<'_>) -> Result<Vec<u16>, ClassReadError> {
1250 let count = reader.read_u2()? as usize;
1251 let mut values = Vec::with_capacity(count);
1252 for _ in 0..count {
1253 values.push(reader.read_u2()?);
1254 }
1255 Ok(values)
1256}
1257
1258fn read_fields(
1259 reader: &mut ByteReader<'_>,
1260 cp: &[CpInfo],
1261) -> Result<Vec<FieldInfo>, ClassReadError> {
1262 let count = reader.read_u2()? as usize;
1263 let mut fields = Vec::with_capacity(count);
1264 for _ in 0..count {
1265 let access_flags = reader.read_u2()?;
1266 let name_index = reader.read_u2()?;
1267 let descriptor_index = reader.read_u2()?;
1268 let attributes = read_attributes(reader, cp)?;
1269 fields.push(FieldInfo {
1270 access_flags,
1271 name_index,
1272 descriptor_index,
1273 attributes,
1274 });
1275 }
1276 Ok(fields)
1277}
1278
1279fn read_methods(
1280 reader: &mut ByteReader<'_>,
1281 cp: &[CpInfo],
1282) -> Result<Vec<MethodInfo>, ClassReadError> {
1283 let count = reader.read_u2()? as usize;
1284 let mut methods = Vec::with_capacity(count);
1285 for _ in 0..count {
1286 let access_flags = reader.read_u2()?;
1287 let name_index = reader.read_u2()?;
1288 let descriptor_index = reader.read_u2()?;
1289 let attributes = read_attributes(reader, cp)?;
1290 methods.push(MethodInfo {
1291 access_flags,
1292 name_index,
1293 descriptor_index,
1294 attributes,
1295 });
1296 }
1297 Ok(methods)
1298}
1299
1300fn read_attributes(
1301 reader: &mut ByteReader<'_>,
1302 cp: &[CpInfo],
1303) -> Result<Vec<AttributeInfo>, ClassReadError> {
1304 let count = reader.read_u2()? as usize;
1305 let mut attributes = Vec::with_capacity(count);
1306 for _ in 0..count {
1307 let name_index = reader.read_u2()?;
1308 let length = reader.read_u4()? as usize;
1309 let name = cp_utf8(cp, name_index)?;
1310 let info = reader.read_bytes(length)?;
1311 let attribute = parse_attribute(name, info, cp)?;
1312 attributes.push(attribute);
1313 }
1314 Ok(attributes)
1315}
1316
1317fn parse_attribute(
1318 name: &str,
1319 info: Vec<u8>,
1320 cp: &[CpInfo],
1321) -> Result<AttributeInfo, ClassReadError> {
1322 let mut reader = ByteReader::new(&info);
1323 let attribute = match name {
1324 "Code" => {
1325 let max_stack = reader.read_u2()?;
1326 let max_locals = reader.read_u2()?;
1327 let code_length = reader.read_u4()? as usize;
1328 let code = reader.read_bytes(code_length)?;
1329 let instructions = parse_code_instructions(&code)?;
1330 let exception_table_length = reader.read_u2()? as usize;
1331 let mut exception_table = Vec::with_capacity(exception_table_length);
1332 for _ in 0..exception_table_length {
1333 exception_table.push(ExceptionTableEntry {
1334 start_pc: reader.read_u2()?,
1335 end_pc: reader.read_u2()?,
1336 handler_pc: reader.read_u2()?,
1337 catch_type: reader.read_u2()?,
1338 });
1339 }
1340 let attributes = read_attributes(&mut reader, cp)?;
1341 let (mut insn_nodes, try_catch_blocks, label_by_offset) =
1342 build_insn_nodes(&code, &exception_table, cp)?;
1343 let line_numbers = attributes.iter().find_map(|attr| match attr {
1344 AttributeInfo::LineNumberTable { entries } => Some(entries.as_slice()),
1345 _ => None,
1346 });
1347 if let Some(entries) = line_numbers {
1348 insn_nodes = attach_line_numbers(insn_nodes, entries, &label_by_offset);
1349 }
1350 AttributeInfo::Code(CodeAttribute {
1351 max_stack,
1352 max_locals,
1353 code,
1354 instructions,
1355 insn_nodes,
1356 exception_table,
1357 try_catch_blocks,
1358 attributes,
1359 })
1360 }
1361 "ConstantValue" => AttributeInfo::ConstantValue {
1362 constantvalue_index: reader.read_u2()?,
1363 },
1364 "Exceptions" => {
1365 let count = reader.read_u2()? as usize;
1366 let mut exception_index_table = Vec::with_capacity(count);
1367 for _ in 0..count {
1368 exception_index_table.push(reader.read_u2()?);
1369 }
1370 AttributeInfo::Exceptions {
1371 exception_index_table,
1372 }
1373 }
1374 "SourceFile" => AttributeInfo::SourceFile {
1375 sourcefile_index: reader.read_u2()?,
1376 },
1377 "LineNumberTable" => {
1378 let count = reader.read_u2()? as usize;
1379 let mut entries = Vec::with_capacity(count);
1380 for _ in 0..count {
1381 entries.push(LineNumber {
1382 start_pc: reader.read_u2()?,
1383 line_number: reader.read_u2()?,
1384 });
1385 }
1386 AttributeInfo::LineNumberTable { entries }
1387 }
1388 "LocalVariableTable" => {
1389 let count = reader.read_u2()? as usize;
1390 let mut entries = Vec::with_capacity(count);
1391 for _ in 0..count {
1392 entries.push(LocalVariable {
1393 start_pc: reader.read_u2()?,
1394 length: reader.read_u2()?,
1395 name_index: reader.read_u2()?,
1396 descriptor_index: reader.read_u2()?,
1397 index: reader.read_u2()?,
1398 });
1399 }
1400 AttributeInfo::LocalVariableTable { entries }
1401 }
1402 "Signature" => AttributeInfo::Signature {
1403 signature_index: reader.read_u2()?,
1404 },
1405 "StackMapTable" => {
1406 let count = reader.read_u2()? as usize;
1407 let mut entries = Vec::with_capacity(count);
1408 for _ in 0..count {
1409 let frame_type = reader.read_u1()?;
1410 let frame = match frame_type {
1411 0..=63 => StackMapFrame::SameFrame {
1412 offset_delta: frame_type as u16,
1413 },
1414 64..=127 => StackMapFrame::SameLocals1StackItemFrame {
1415 offset_delta: (frame_type - 64) as u16,
1416 stack: parse_verification_type(&mut reader)?,
1417 },
1418 247 => StackMapFrame::SameLocals1StackItemFrameExtended {
1419 offset_delta: reader.read_u2()?,
1420 stack: parse_verification_type(&mut reader)?,
1421 },
1422 248..=250 => StackMapFrame::ChopFrame {
1423 offset_delta: reader.read_u2()?,
1424 k: 251 - frame_type,
1425 },
1426 251 => StackMapFrame::SameFrameExtended {
1427 offset_delta: reader.read_u2()?,
1428 },
1429 252..=254 => {
1430 let offset_delta = reader.read_u2()?;
1431 let locals_count = (frame_type - 251) as usize;
1432 let mut locals = Vec::with_capacity(locals_count);
1433 for _ in 0..locals_count {
1434 locals.push(parse_verification_type(&mut reader)?);
1435 }
1436 StackMapFrame::AppendFrame {
1437 offset_delta,
1438 locals,
1439 }
1440 }
1441 255 => {
1442 let offset_delta = reader.read_u2()?;
1443 let locals_count = reader.read_u2()? as usize;
1444 let mut locals = Vec::with_capacity(locals_count);
1445 for _ in 0..locals_count {
1446 locals.push(parse_verification_type(&mut reader)?);
1447 }
1448 let stack_count = reader.read_u2()? as usize;
1449 let mut stack = Vec::with_capacity(stack_count);
1450 for _ in 0..stack_count {
1451 stack.push(parse_verification_type(&mut reader)?);
1452 }
1453 StackMapFrame::FullFrame {
1454 offset_delta,
1455 locals,
1456 stack,
1457 }
1458 }
1459 _ => {
1460 return Err(ClassReadError::InvalidAttribute(
1461 "StackMapTable".to_string(),
1462 ));
1463 }
1464 };
1465 entries.push(frame);
1466 }
1467 AttributeInfo::StackMapTable { entries }
1468 }
1469 "Deprecated" => AttributeInfo::Deprecated,
1470 "Synthetic" => AttributeInfo::Synthetic,
1471 "InnerClasses" => {
1472 let count = reader.read_u2()? as usize;
1473 let mut classes = Vec::with_capacity(count);
1474 for _ in 0..count {
1475 classes.push(InnerClass {
1476 inner_class_info_index: reader.read_u2()?,
1477 outer_class_info_index: reader.read_u2()?,
1478 inner_name_index: reader.read_u2()?,
1479 inner_class_access_flags: reader.read_u2()?,
1480 });
1481 }
1482 AttributeInfo::InnerClasses { classes }
1483 }
1484 "EnclosingMethod" => AttributeInfo::EnclosingMethod {
1485 class_index: reader.read_u2()?,
1486 method_index: reader.read_u2()?,
1487 },
1488 "Module" => AttributeInfo::Module(parse_module_attribute(&mut reader)?),
1489 "ModulePackages" => {
1490 let count = reader.read_u2()? as usize;
1491 let mut package_index_table = Vec::with_capacity(count);
1492 for _ in 0..count {
1493 package_index_table.push(reader.read_u2()?);
1494 }
1495 AttributeInfo::ModulePackages {
1496 package_index_table,
1497 }
1498 }
1499 "ModuleMainClass" => AttributeInfo::ModuleMainClass {
1500 main_class_index: reader.read_u2()?,
1501 },
1502 "BootstrapMethods" => {
1503 let count = reader.read_u2()? as usize;
1504 let mut methods = Vec::with_capacity(count);
1505 for _ in 0..count {
1506 let bootstrap_method_ref = reader.read_u2()?;
1507 let arg_count = reader.read_u2()? as usize;
1508 let mut bootstrap_arguments = Vec::with_capacity(arg_count);
1509 for _ in 0..arg_count {
1510 bootstrap_arguments.push(reader.read_u2()?);
1511 }
1512 methods.push(BootstrapMethod {
1513 bootstrap_method_ref,
1514 bootstrap_arguments,
1515 });
1516 }
1517 AttributeInfo::BootstrapMethods { methods }
1518 }
1519 "MethodParameters" => {
1520 let count = reader.read_u1()? as usize;
1521 let mut parameters = Vec::with_capacity(count);
1522 for _ in 0..count {
1523 parameters.push(MethodParameter {
1524 name_index: reader.read_u2()?,
1525 access_flags: reader.read_u2()?,
1526 });
1527 }
1528 AttributeInfo::MethodParameters { parameters }
1529 }
1530 "RuntimeVisibleAnnotations" => {
1531 let annotations = parse_annotations(&mut reader)?;
1532 AttributeInfo::RuntimeVisibleAnnotations { annotations }
1533 }
1534 "RuntimeInvisibleAnnotations" => {
1535 let annotations = parse_annotations(&mut reader)?;
1536 AttributeInfo::RuntimeInvisibleAnnotations { annotations }
1537 }
1538 "RuntimeVisibleParameterAnnotations" => {
1539 let parameters = parse_parameter_annotations(&mut reader)?;
1540 AttributeInfo::RuntimeVisibleParameterAnnotations { parameters }
1541 }
1542 "RuntimeInvisibleParameterAnnotations" => {
1543 let parameters = parse_parameter_annotations(&mut reader)?;
1544 AttributeInfo::RuntimeInvisibleParameterAnnotations { parameters }
1545 }
1546 "RuntimeVisibleTypeAnnotations" => {
1547 let annotations = parse_type_annotations(&mut reader)?;
1548 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations }
1549 }
1550 "RuntimeInvisibleTypeAnnotations" => {
1551 let annotations = parse_type_annotations(&mut reader)?;
1552 AttributeInfo::RuntimeInvisibleTypeAnnotations { annotations }
1553 }
1554 "PermittedSubclasses" => {
1555 let count = reader.read_u2()? as usize;
1556 let mut classes = Vec::with_capacity(count);
1557 for _ in 0..count {
1558 classes.push(reader.read_u2()?);
1559 }
1560 AttributeInfo::PermittedSubclasses { classes }
1561 }
1562 "Record" => {
1563 let count = reader.read_u2()? as usize;
1564 let mut components = Vec::with_capacity(count);
1565 for _ in 0..count {
1566 let name_index = reader.read_u2()?;
1567 let descriptor_index = reader.read_u2()?;
1568 let attributes = read_attributes(&mut reader, cp)?;
1569 components.push(RecordComponent {
1570 name_index,
1571 descriptor_index,
1572 attributes,
1573 });
1574 }
1575 AttributeInfo::Record { components }
1576 }
1577 _ => {
1578 return Ok(AttributeInfo::Unknown {
1579 name: name.to_string(),
1580 info,
1581 });
1582 }
1583 };
1584
1585 if reader.remaining() != 0 {
1586 return Err(ClassReadError::InvalidAttribute(name.to_string()));
1587 }
1588
1589 Ok(attribute)
1590}
1591
1592fn parse_module_attribute(reader: &mut ByteReader<'_>) -> Result<ModuleAttribute, ClassReadError> {
1593 let module_name_index = reader.read_u2()?;
1594 let module_flags = reader.read_u2()?;
1595 let module_version_index = reader.read_u2()?;
1596
1597 let requires_count = reader.read_u2()? as usize;
1598 let mut requires = Vec::with_capacity(requires_count);
1599 for _ in 0..requires_count {
1600 requires.push(ModuleRequire {
1601 requires_index: reader.read_u2()?,
1602 requires_flags: reader.read_u2()?,
1603 requires_version_index: reader.read_u2()?,
1604 });
1605 }
1606
1607 let exports_count = reader.read_u2()? as usize;
1608 let mut exports = Vec::with_capacity(exports_count);
1609 for _ in 0..exports_count {
1610 let exports_index = reader.read_u2()?;
1611 let exports_flags = reader.read_u2()?;
1612 let exports_to_count = reader.read_u2()? as usize;
1613 let mut exports_to_index = Vec::with_capacity(exports_to_count);
1614 for _ in 0..exports_to_count {
1615 exports_to_index.push(reader.read_u2()?);
1616 }
1617 exports.push(ModuleExport {
1618 exports_index,
1619 exports_flags,
1620 exports_to_index,
1621 });
1622 }
1623
1624 let opens_count = reader.read_u2()? as usize;
1625 let mut opens = Vec::with_capacity(opens_count);
1626 for _ in 0..opens_count {
1627 let opens_index = reader.read_u2()?;
1628 let opens_flags = reader.read_u2()?;
1629 let opens_to_count = reader.read_u2()? as usize;
1630 let mut opens_to_index = Vec::with_capacity(opens_to_count);
1631 for _ in 0..opens_to_count {
1632 opens_to_index.push(reader.read_u2()?);
1633 }
1634 opens.push(ModuleOpen {
1635 opens_index,
1636 opens_flags,
1637 opens_to_index,
1638 });
1639 }
1640
1641 let uses_count = reader.read_u2()? as usize;
1642 let mut uses_index = Vec::with_capacity(uses_count);
1643 for _ in 0..uses_count {
1644 uses_index.push(reader.read_u2()?);
1645 }
1646
1647 let provides_count = reader.read_u2()? as usize;
1648 let mut provides = Vec::with_capacity(provides_count);
1649 for _ in 0..provides_count {
1650 let provides_index = reader.read_u2()?;
1651 let provides_with_count = reader.read_u2()? as usize;
1652 let mut provides_with_index = Vec::with_capacity(provides_with_count);
1653 for _ in 0..provides_with_count {
1654 provides_with_index.push(reader.read_u2()?);
1655 }
1656 provides.push(ModuleProvide {
1657 provides_index,
1658 provides_with_index,
1659 });
1660 }
1661
1662 Ok(ModuleAttribute {
1663 module_name_index,
1664 module_flags,
1665 module_version_index,
1666 requires,
1667 exports,
1668 opens,
1669 uses_index,
1670 provides,
1671 })
1672}
1673
1674fn parse_annotations(reader: &mut ByteReader) -> Result<Vec<Annotation>, ClassReadError> {
1675 let num = reader.read_u2()? as usize;
1676 let mut out = Vec::with_capacity(num);
1677 for _ in 0..num {
1678 out.push(parse_annotation(reader)?);
1679 }
1680 Ok(out)
1681}
1682
1683fn parse_annotation(reader: &mut ByteReader) -> Result<Annotation, ClassReadError> {
1684 let type_descriptor_index = reader.read_u2()?;
1685 let num_pairs = reader.read_u2()? as usize;
1686 let mut element_value_pairs = Vec::with_capacity(num_pairs);
1687 for _ in 0..num_pairs {
1688 let element_name_index = reader.read_u2()?;
1689 let value = parse_element_value(reader)?;
1690 element_value_pairs.push(ElementValuePair {
1691 element_name_index,
1692 value,
1693 });
1694 }
1695 Ok(Annotation {
1696 type_descriptor_index,
1697 element_value_pairs,
1698 })
1699}
1700
1701fn parse_parameter_annotations(
1702 reader: &mut ByteReader,
1703) -> Result<ParameterAnnotations, ClassReadError> {
1704 let num_params = reader.read_u1()? as usize;
1705 let mut parameters = Vec::with_capacity(num_params);
1706 for _ in 0..num_params {
1707 let num_ann = reader.read_u2()? as usize;
1708 let mut anns = Vec::with_capacity(num_ann);
1709 for _ in 0..num_ann {
1710 anns.push(parse_annotation(reader)?);
1711 }
1712 parameters.push(anns);
1713 }
1714 Ok(ParameterAnnotations { parameters })
1715}
1716
1717fn parse_type_annotations(reader: &mut ByteReader) -> Result<Vec<TypeAnnotation>, ClassReadError> {
1718 let num = reader.read_u2()? as usize;
1719 let mut out = Vec::with_capacity(num);
1720 for _ in 0..num {
1721 out.push(parse_type_annotation(reader)?);
1722 }
1723 Ok(out)
1724}
1725
1726fn parse_type_annotation(reader: &mut ByteReader) -> Result<TypeAnnotation, ClassReadError> {
1727 let target_type = reader.read_u1()?;
1728 let target_info = parse_type_annotation_target_info(reader, target_type)?;
1729 let target_path = parse_type_path(reader)?;
1730 let annotation = parse_annotation(reader)?;
1731 Ok(TypeAnnotation {
1732 target_type,
1733 target_info,
1734 target_path,
1735 annotation,
1736 })
1737}
1738
1739fn parse_type_path(reader: &mut ByteReader) -> Result<TypePath, ClassReadError> {
1740 let path_length = reader.read_u1()? as usize;
1741 let mut path = Vec::with_capacity(path_length);
1742 for _ in 0..path_length {
1743 path.push(TypePathEntry {
1744 type_path_kind: reader.read_u1()?,
1745 type_argument_index: reader.read_u1()?,
1746 });
1747 }
1748 Ok(TypePath { path })
1749}
1750
1751fn parse_type_annotation_target_info(
1752 reader: &mut ByteReader,
1753 target_type: u8,
1754) -> Result<TypeAnnotationTargetInfo, ClassReadError> {
1755 use crate::constants::*;
1756
1757 let ti = match target_type {
1758 TA_TARGET_CLASS_TYPE_PARAMETER | TA_TARGET_METHOD_TYPE_PARAMETER => {
1759 TypeAnnotationTargetInfo::TypeParameter {
1760 type_parameter_index: reader.read_u1()?,
1761 }
1762 }
1763
1764 TA_TARGET_CLASS_EXTENDS => TypeAnnotationTargetInfo::Supertype {
1765 supertype_index: reader.read_u2()?,
1766 },
1767
1768 TA_TARGET_CLASS_TYPE_PARAMETER_BOUND | TA_TARGET_METHOD_TYPE_PARAMETER_BOUND => {
1769 TypeAnnotationTargetInfo::TypeParameterBound {
1770 type_parameter_index: reader.read_u1()?,
1771 bound_index: reader.read_u1()?,
1772 }
1773 }
1774
1775 TA_TARGET_FIELD | TA_TARGET_METHOD_RETURN | TA_TARGET_METHOD_RECEIVER => {
1776 TypeAnnotationTargetInfo::Empty
1777 }
1778
1779 TA_TARGET_METHOD_FORMAL_PARAMETER => TypeAnnotationTargetInfo::FormalParameter {
1780 formal_parameter_index: reader.read_u1()?,
1781 },
1782
1783 TA_TARGET_THROWS => TypeAnnotationTargetInfo::Throws {
1784 throws_type_index: reader.read_u2()?,
1785 },
1786
1787 TA_TARGET_LOCAL_VARIABLE | TA_TARGET_RESOURCE_VARIABLE => {
1788 let table_length = reader.read_u2()? as usize;
1789 let mut table = Vec::with_capacity(table_length);
1790 for _ in 0..table_length {
1791 table.push(LocalVarTargetTableEntry {
1792 start_pc: reader.read_u2()?,
1793 length: reader.read_u2()?,
1794 index: reader.read_u2()?,
1795 });
1796 }
1797 TypeAnnotationTargetInfo::LocalVar { table }
1798 }
1799
1800 TA_TARGET_EXCEPTION_PARAMETER => TypeAnnotationTargetInfo::Catch {
1801 exception_table_index: reader.read_u2()?,
1802 },
1803
1804 TA_TARGET_INSTANCEOF
1805 | TA_TARGET_NEW
1806 | TA_TARGET_CONSTRUCTOR_REFERENCE_RECEIVER
1807 | TA_TARGET_METHOD_REFERENCE_RECEIVER => TypeAnnotationTargetInfo::Offset {
1808 offset: reader.read_u2()?,
1809 },
1810
1811 TA_TARGET_CAST
1812 | TA_TARGET_CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1813 | TA_TARGET_METHOD_INVOCATION_TYPE_ARGUMENT
1814 | TA_TARGET_CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1815 | TA_TARGET_METHOD_REFERENCE_TYPE_ARGUMENT => TypeAnnotationTargetInfo::TypeArgument {
1816 offset: reader.read_u2()?,
1817 type_argument_index: reader.read_u1()?,
1818 },
1819
1820 _ => {
1821 return Err(ClassReadError::InvalidAttribute(format!(
1822 "TypeAnnotationTargetInfo(target_type=0x{:02X})",
1823 target_type
1824 )));
1825 }
1826 };
1827
1828 Ok(ti)
1829}
1830
1831fn parse_element_value(reader: &mut ByteReader) -> Result<ElementValue, ClassReadError> {
1832 let tag = reader.read_u1()?;
1833 let v = match tag {
1834 b'B' | b'C' | b'D' | b'F' | b'I' | b'J' | b'S' | b'Z' | b's' => {
1835 ElementValue::ConstValueIndex {
1836 tag,
1837 const_value_index: reader.read_u2()?,
1838 }
1839 }
1840 b'e' => ElementValue::EnumConstValue {
1841 type_name_index: reader.read_u2()?,
1842 const_name_index: reader.read_u2()?,
1843 },
1844 b'c' => ElementValue::ClassInfoIndex {
1845 class_info_index: reader.read_u2()?,
1846 },
1847 b'@' => ElementValue::AnnotationValue(Box::new(parse_annotation(reader)?)),
1848 b'[' => {
1849 let n = reader.read_u2()? as usize;
1850 let mut items = Vec::with_capacity(n);
1851 for _ in 0..n {
1852 items.push(parse_element_value(reader)?);
1853 }
1854 ElementValue::ArrayValue(items)
1855 }
1856 _ => {
1857 return Err(ClassReadError::InvalidAttribute(
1858 "AnnotationElementValue".to_string(),
1859 ));
1860 }
1861 };
1862 Ok(v)
1863}
1864
1865fn parse_verification_type(
1866 reader: &mut ByteReader<'_>,
1867) -> Result<VerificationTypeInfo, ClassReadError> {
1868 let tag = reader.read_u1()?;
1869 let kind = match tag {
1870 0 => VerificationTypeInfo::Top,
1871 1 => VerificationTypeInfo::Integer,
1872 2 => VerificationTypeInfo::Float,
1873 3 => VerificationTypeInfo::Double,
1874 4 => VerificationTypeInfo::Long,
1875 5 => VerificationTypeInfo::Null,
1876 6 => VerificationTypeInfo::UninitializedThis,
1877 7 => VerificationTypeInfo::Object {
1878 cpool_index: reader.read_u2()?,
1879 },
1880 8 => VerificationTypeInfo::Uninitialized {
1881 offset: reader.read_u2()?,
1882 },
1883 _ => {
1884 return Err(ClassReadError::InvalidAttribute(
1885 "StackMapTable".to_string(),
1886 ));
1887 }
1888 };
1889 Ok(kind)
1890}
1891
1892fn cp_utf8(cp: &[CpInfo], index: u16) -> Result<&str, ClassReadError> {
1893 match cp.get(index as usize) {
1894 Some(CpInfo::Utf8(value)) => Ok(value.as_str()),
1895 _ => Err(ClassReadError::InvalidIndex(index)),
1896 }
1897}
1898
1899fn cp_class_name(cp: &[CpInfo], index: u16) -> Result<&str, ClassReadError> {
1900 match cp.get(index as usize) {
1901 Some(CpInfo::Class { name_index }) => cp_utf8(cp, *name_index),
1902 _ => Err(ClassReadError::InvalidIndex(index)),
1903 }
1904}
1905
1906fn cp_name_and_type(cp: &[CpInfo], index: u16) -> Result<(&str, &str), ClassReadError> {
1907 match cp.get(index as usize) {
1908 Some(CpInfo::NameAndType {
1909 name_index,
1910 descriptor_index,
1911 }) => Ok((cp_utf8(cp, *name_index)?, cp_utf8(cp, *descriptor_index)?)),
1912 _ => Err(ClassReadError::InvalidIndex(index)),
1913 }
1914}
1915
1916fn cp_field_ref(cp: &[CpInfo], index: u16) -> Result<(&str, &str, &str), ClassReadError> {
1917 match cp.get(index as usize) {
1918 Some(CpInfo::Fieldref {
1919 class_index,
1920 name_and_type_index,
1921 }) => {
1922 let owner = cp_class_name(cp, *class_index)?;
1923 let (name, desc) = cp_name_and_type(cp, *name_and_type_index)?;
1924 Ok((owner, name, desc))
1925 }
1926 _ => Err(ClassReadError::InvalidIndex(index)),
1927 }
1928}
1929
1930fn cp_method_ref(cp: &[CpInfo], index: u16) -> Result<(&str, &str, &str, bool), ClassReadError> {
1931 match cp.get(index as usize) {
1932 Some(CpInfo::Methodref {
1933 class_index,
1934 name_and_type_index,
1935 }) => {
1936 let owner = cp_class_name(cp, *class_index)?;
1937 let (name, desc) = cp_name_and_type(cp, *name_and_type_index)?;
1938 Ok((owner, name, desc, false))
1939 }
1940 Some(CpInfo::InterfaceMethodref {
1941 class_index,
1942 name_and_type_index,
1943 }) => {
1944 let owner = cp_class_name(cp, *class_index)?;
1945 let (name, desc) = cp_name_and_type(cp, *name_and_type_index)?;
1946 Ok((owner, name, desc, true))
1947 }
1948 _ => Err(ClassReadError::InvalidIndex(index)),
1949 }
1950}
1951
1952fn cp_invoke_dynamic(cp: &[CpInfo], index: u16) -> Result<(&str, &str), ClassReadError> {
1953 match cp.get(index as usize) {
1954 Some(CpInfo::InvokeDynamic {
1955 name_and_type_index,
1956 ..
1957 }) => cp_name_and_type(cp, *name_and_type_index),
1958 _ => Err(ClassReadError::InvalidIndex(index)),
1959 }
1960}
1961
1962fn cp_ldc_constant(cp: &[CpInfo], index: u16) -> Result<LdcConstant, ClassReadError> {
1963 match cp.get(index as usize) {
1964 Some(CpInfo::Integer(value)) => Ok(LdcConstant::Integer(*value)),
1965 Some(CpInfo::Float(value)) => Ok(LdcConstant::Float(*value)),
1966 Some(CpInfo::Long(value)) => Ok(LdcConstant::Long(*value)),
1967 Some(CpInfo::Double(value)) => Ok(LdcConstant::Double(*value)),
1968 Some(CpInfo::String { string_index }) => {
1969 Ok(LdcConstant::String(cp_utf8(cp, *string_index)?.to_string()))
1970 }
1971 Some(CpInfo::Class { name_index }) => {
1972 Ok(LdcConstant::Class(cp_utf8(cp, *name_index)?.to_string()))
1973 }
1974 Some(CpInfo::MethodType { descriptor_index }) => Ok(LdcConstant::MethodType(
1975 cp_utf8(cp, *descriptor_index)?.to_string(),
1976 )),
1977 Some(CpInfo::MethodHandle {
1978 reference_kind,
1979 reference_index,
1980 }) => Ok(LdcConstant::MethodHandle {
1981 reference_kind: *reference_kind,
1982 reference_index: *reference_index,
1983 }),
1984 Some(CpInfo::Dynamic { .. }) => Ok(LdcConstant::Dynamic),
1985 _ => Err(ClassReadError::InvalidIndex(index)),
1986 }
1987}
1988
1989fn decode_modified_utf8(bytes: &[u8]) -> Result<String, ClassReadError> {
1990 let mut code_units = Vec::with_capacity(bytes.len());
1991 let mut i = 0;
1992 while i < bytes.len() {
1993 let byte = bytes[i];
1994 if byte & 0x80 == 0 {
1995 code_units.push(byte as u16);
1996 i += 1;
1997 } else if byte & 0xE0 == 0xC0 {
1998 if i + 1 >= bytes.len() {
1999 return Err(ClassReadError::Utf8Error("truncated 2-byte".to_string()));
2000 }
2001 let byte2 = bytes[i + 1];
2002 if byte2 & 0xC0 != 0x80 {
2003 return Err(ClassReadError::Utf8Error("invalid 2-byte".to_string()));
2004 }
2005 let value = (((byte & 0x1F) as u16) << 6) | ((byte2 & 0x3F) as u16);
2006 code_units.push(value);
2007 i += 2;
2008 } else if byte & 0xF0 == 0xE0 {
2009 if i + 2 >= bytes.len() {
2010 return Err(ClassReadError::Utf8Error("truncated 3-byte".to_string()));
2011 }
2012 let byte2 = bytes[i + 1];
2013 let byte3 = bytes[i + 2];
2014 if byte2 & 0xC0 != 0x80 || byte3 & 0xC0 != 0x80 {
2015 return Err(ClassReadError::Utf8Error("invalid 3-byte".to_string()));
2016 }
2017 let value = (((byte & 0x0F) as u16) << 12)
2018 | (((byte2 & 0x3F) as u16) << 6)
2019 | ((byte3 & 0x3F) as u16);
2020 code_units.push(value);
2021 i += 3;
2022 } else {
2023 return Err(ClassReadError::Utf8Error(
2024 "invalid leading byte".to_string(),
2025 ));
2026 }
2027 }
2028
2029 String::from_utf16(&code_units)
2030 .map_err(|_| ClassReadError::Utf8Error("invalid utf16".to_string()))
2031}
2032
2033fn parse_code_instructions(code: &[u8]) -> Result<Vec<Insn>, ClassReadError> {
2034 let mut reader = ByteReader::new(code);
2035 let mut insns = Vec::new();
2036
2037 while reader.remaining() > 0 {
2038 let opcode_offset = reader.pos();
2039 let opcode = reader.read_u1()?;
2040 let insn = match opcode {
2041 opcodes::NOP..=opcodes::DCONST_1 => Insn::Simple(opcode.into()),
2042 opcodes::BIPUSH => Insn::Int(IntInsnNode {
2043 insn: opcode.into(),
2044 operand: reader.read_i1()? as i32,
2045 }),
2046 opcodes::SIPUSH => Insn::Int(IntInsnNode {
2047 insn: opcode.into(),
2048 operand: reader.read_i2()? as i32,
2049 }),
2050 opcodes::LDC => Insn::Ldc(LdcInsnNode {
2051 insn: opcode.into(),
2052 value: LdcValue::Index(reader.read_u1()? as u16),
2053 }),
2054 opcodes::LDC_W | opcodes::LDC2_W => Insn::Ldc(LdcInsnNode {
2055 insn: opcode.into(),
2056 value: LdcValue::Index(reader.read_u2()?),
2057 }),
2058 opcodes::ILOAD..=opcodes::ALOAD => Insn::Var(VarInsnNode {
2059 insn: opcode.into(),
2060 var_index: reader.read_u1()? as u16,
2061 }),
2062 opcodes::ILOAD_0..=opcodes::SALOAD => Insn::Simple(opcode.into()),
2063 opcodes::ISTORE..=opcodes::ASTORE => Insn::Var(VarInsnNode {
2064 insn: opcode.into(),
2065 var_index: reader.read_u1()? as u16,
2066 }),
2067 opcodes::ISTORE_0..=opcodes::SASTORE => Insn::Simple(opcode.into()),
2068 opcodes::POP..=opcodes::LXOR => Insn::Simple(opcode.into()),
2069 opcodes::IINC => Insn::Iinc(IincInsnNode {
2070 insn: opcode.into(),
2071 var_index: reader.read_u1()? as u16,
2072 increment: reader.read_i1()? as i16,
2073 }),
2074 opcodes::I2L..=opcodes::DCMPG => Insn::Simple(opcode.into()),
2075 opcodes::IFEQ..=opcodes::JSR => Insn::Jump(JumpInsnNode {
2076 insn: opcode.into(),
2077 offset: reader.read_i2()? as i32,
2078 }),
2079 opcodes::RET => Insn::Var(VarInsnNode {
2080 insn: opcode.into(),
2081 var_index: reader.read_u1()? as u16,
2082 }),
2083 opcodes::TABLESWITCH => read_table_switch(&mut reader, opcode_offset)?,
2084 opcodes::LOOKUPSWITCH => read_lookup_switch(&mut reader, opcode_offset)?,
2085 opcodes::IRETURN..=opcodes::RETURN => Insn::Simple(InsnNode { opcode }),
2086 opcodes::GETSTATIC..=opcodes::PUTFIELD => Insn::Field(FieldInsnNode {
2087 insn: opcode.into(),
2088 field_ref: MemberRef::Index(reader.read_u2()?),
2089 }),
2090 opcodes::INVOKEVIRTUAL..=opcodes::INVOKESTATIC => Insn::Method(MethodInsnNode {
2091 insn: opcode.into(),
2092 method_ref: MemberRef::Index(reader.read_u2()?),
2093 }),
2094 opcodes::INVOKEINTERFACE => {
2095 let method_index = reader.read_u2()?;
2096 let count = reader.read_u1()?;
2097 let _ = reader.read_u1()?;
2098 Insn::InvokeInterface(InvokeInterfaceInsnNode {
2099 insn: opcode.into(),
2100 method_index,
2101 count,
2102 })
2103 }
2104 opcodes::INVOKEDYNAMIC => {
2105 let method_index = reader.read_u2()?;
2106 let _ = reader.read_u2()?;
2107 Insn::InvokeDynamic(InvokeDynamicInsnNode::from_index(method_index))
2108 }
2109 opcodes::NEW => Insn::Type(TypeInsnNode {
2110 insn: opcode.into(),
2111 type_index: reader.read_u2()?,
2112 }),
2113 opcodes::NEWARRAY => Insn::Int(IntInsnNode {
2114 insn: opcode.into(),
2115 operand: reader.read_u1()? as i32,
2116 }),
2117 opcodes::ANEWARRAY => Insn::Type(TypeInsnNode {
2118 insn: opcode.into(),
2119 type_index: reader.read_u2()?,
2120 }),
2121 opcodes::ARRAYLENGTH | opcodes::ATHROW => Insn::Simple(opcode.into()),
2122 opcodes::CHECKCAST | opcodes::INSTANCEOF => Insn::Type(TypeInsnNode {
2123 insn: opcode.into(),
2124 type_index: reader.read_u2()?,
2125 }),
2126 opcodes::MONITORENTER | opcodes::MONITOREXIT => Insn::Simple(opcode.into()),
2127 opcodes::WIDE => read_wide(&mut reader)?,
2128 opcodes::MULTIANEWARRAY => Insn::MultiANewArray(MultiANewArrayInsnNode {
2129 insn: opcode.into(),
2130 type_index: reader.read_u2()?,
2131 dimensions: reader.read_u1()?,
2132 }),
2133 opcodes::IFNULL | opcodes::IFNONNULL => Insn::Jump(JumpInsnNode {
2134 insn: opcode.into(),
2135 offset: reader.read_i2()? as i32,
2136 }),
2137 opcodes::GOTO_W | opcodes::JSR_W => Insn::Jump(JumpInsnNode {
2138 insn: opcode.into(),
2139 offset: reader.read_i4()?,
2140 }),
2141 opcodes::BREAKPOINT => Insn::Simple(opcode.into()),
2142 opcodes::IMPDEP1 | opcodes::IMPDEP2 => Insn::Simple(opcode.into()),
2143 _ => {
2144 return Err(ClassReadError::InvalidOpcode {
2145 opcode,
2146 offset: opcode_offset,
2147 });
2148 }
2149 };
2150
2151 insns.push(insn);
2152 }
2153
2154 Ok(insns)
2155}
2156
2157pub(crate) fn parse_code_instructions_public(code: &[u8]) -> Result<Vec<Insn>, ClassReadError> {
2158 parse_code_instructions(code)
2159}
2160
2161#[derive(Debug, Clone)]
2162struct ParsedInstruction {
2163 offset: u16,
2164 insn: Insn,
2165}
2166
2167fn parse_code_instructions_with_offsets(
2168 code: &[u8],
2169) -> Result<Vec<ParsedInstruction>, ClassReadError> {
2170 let mut reader = ByteReader::new(code);
2171 let mut insns = Vec::new();
2172
2173 while reader.remaining() > 0 {
2174 let opcode_offset = reader.pos();
2175 let opcode = reader.read_u1()?;
2176 let insn = match opcode {
2177 opcodes::NOP..=opcodes::DCONST_1 => Insn::Simple(opcode.into()),
2178 opcodes::BIPUSH => Insn::Int(IntInsnNode {
2179 insn: opcode.into(),
2180 operand: reader.read_i1()? as i32,
2181 }),
2182 opcodes::SIPUSH => Insn::Int(IntInsnNode {
2183 insn: opcode.into(),
2184 operand: reader.read_i2()? as i32,
2185 }),
2186 opcodes::LDC => Insn::Ldc(LdcInsnNode {
2187 insn: opcode.into(),
2188 value: LdcValue::Index(reader.read_u1()? as u16),
2189 }),
2190 opcodes::LDC_W | opcodes::LDC2_W => Insn::Ldc(LdcInsnNode {
2191 insn: opcode.into(),
2192 value: LdcValue::Index(reader.read_u2()?),
2193 }),
2194 opcodes::ILOAD..=opcodes::ALOAD => Insn::Var(VarInsnNode {
2195 insn: opcode.into(),
2196 var_index: reader.read_u1()? as u16,
2197 }),
2198 opcodes::ILOAD_0..=opcodes::SALOAD => Insn::Simple(opcode.into()),
2199 opcodes::ISTORE..=opcodes::ASTORE => Insn::Var(VarInsnNode {
2200 insn: opcode.into(),
2201 var_index: reader.read_u1()? as u16,
2202 }),
2203 opcodes::ISTORE_0..=opcodes::SASTORE => Insn::Simple(opcode.into()),
2204 opcodes::POP..=opcodes::LXOR => Insn::Simple(opcode.into()),
2205 opcodes::IINC => Insn::Iinc(IincInsnNode {
2206 insn: opcode.into(),
2207 var_index: reader.read_u1()? as u16,
2208 increment: reader.read_i1()? as i16,
2209 }),
2210 opcodes::I2L..=opcodes::DCMPG => Insn::Simple(opcode.into()),
2211 opcodes::IFEQ..=opcodes::JSR => Insn::Jump(JumpInsnNode {
2212 insn: opcode.into(),
2213 offset: reader.read_i2()? as i32,
2214 }),
2215 opcodes::RET => Insn::Var(VarInsnNode {
2216 insn: opcode.into(),
2217 var_index: reader.read_u1()? as u16,
2218 }),
2219 opcodes::TABLESWITCH => read_table_switch(&mut reader, opcode_offset)?,
2220 opcodes::LOOKUPSWITCH => read_lookup_switch(&mut reader, opcode_offset)?,
2221 opcodes::IRETURN..=opcodes::RETURN => Insn::Simple(opcode.into()),
2222 opcodes::GETSTATIC..=opcodes::PUTFIELD => Insn::Field(FieldInsnNode {
2223 insn: opcode.into(),
2224 field_ref: MemberRef::Index(reader.read_u2()?),
2225 }),
2226 opcodes::INVOKEVIRTUAL..=opcodes::INVOKESTATIC => Insn::Method(MethodInsnNode {
2227 insn: opcode.into(),
2228 method_ref: MemberRef::Index(reader.read_u2()?),
2229 }),
2230 opcodes::INVOKEINTERFACE => {
2231 let method_index = reader.read_u2()?;
2232 let count = reader.read_u1()?;
2233 let _ = reader.read_u1()?;
2234 Insn::InvokeInterface(InvokeInterfaceInsnNode {
2235 insn: opcode.into(),
2236 method_index,
2237 count,
2238 })
2239 }
2240 opcodes::INVOKEDYNAMIC => {
2241 let method_index = reader.read_u2()?;
2242 let _ = reader.read_u2()?;
2243 Insn::InvokeDynamic(InvokeDynamicInsnNode::from_index(method_index))
2244 }
2245 opcodes::NEW => Insn::Type(TypeInsnNode {
2246 insn: opcode.into(),
2247 type_index: reader.read_u2()?,
2248 }),
2249 opcodes::NEWARRAY => Insn::Int(IntInsnNode {
2250 insn: opcode.into(),
2251 operand: reader.read_u1()? as i32,
2252 }),
2253 opcodes::ANEWARRAY => Insn::Type(TypeInsnNode {
2254 insn: opcode.into(),
2255 type_index: reader.read_u2()?,
2256 }),
2257 opcodes::ARRAYLENGTH | opcodes::ATHROW => Insn::Simple(opcode.into()),
2258 opcodes::CHECKCAST | opcodes::INSTANCEOF => Insn::Type(TypeInsnNode {
2259 insn: opcode.into(),
2260 type_index: reader.read_u2()?,
2261 }),
2262 opcodes::MONITORENTER | opcodes::MONITOREXIT => Insn::Simple(opcode.into()),
2263 opcodes::WIDE => read_wide(&mut reader)?,
2264 opcodes::MULTIANEWARRAY => Insn::MultiANewArray(MultiANewArrayInsnNode {
2265 insn: opcode.into(),
2266 type_index: reader.read_u2()?,
2267 dimensions: reader.read_u1()?,
2268 }),
2269 opcodes::IFNULL | opcodes::IFNONNULL => Insn::Jump(JumpInsnNode {
2270 insn: opcode.into(),
2271 offset: reader.read_i2()? as i32,
2272 }),
2273 opcodes::GOTO_W | opcodes::JSR_W => Insn::Jump(JumpInsnNode {
2274 insn: opcode.into(),
2275 offset: reader.read_i4()?,
2276 }),
2277 opcodes::BREAKPOINT => Insn::Simple(opcode.into()),
2278 opcodes::IMPDEP1 | opcodes::IMPDEP2 => Insn::Simple(opcode.into()),
2279 _ => {
2280 return Err(ClassReadError::InvalidOpcode {
2281 opcode,
2282 offset: opcode_offset,
2283 });
2284 }
2285 };
2286
2287 insns.push(ParsedInstruction {
2288 offset: opcode_offset as u16,
2289 insn,
2290 });
2291 }
2292
2293 Ok(insns)
2294}
2295
2296fn build_insn_nodes(
2297 code: &[u8],
2298 exception_table: &[ExceptionTableEntry],
2299 cp: &[CpInfo],
2300) -> Result<
2301 (
2302 Vec<AbstractInsnNode>,
2303 Vec<TryCatchBlockNode>,
2304 std::collections::HashMap<u16, LabelNode>,
2305 ),
2306 ClassReadError,
2307> {
2308 let instructions = parse_code_instructions_with_offsets(code)?;
2309 let mut offsets = std::collections::HashSet::new();
2310 for instruction in &instructions {
2311 offsets.insert(instruction.offset);
2312 match &instruction.insn {
2313 Insn::Jump(node) => {
2314 offsets.insert((instruction.offset as i32 + node.offset) as u16);
2315 }
2316 Insn::TableSwitch(node) => {
2317 offsets.insert((instruction.offset as i32 + node.default_offset) as u16);
2318 for offset in &node.offsets {
2319 offsets.insert((instruction.offset as i32 + *offset) as u16);
2320 }
2321 }
2322 Insn::LookupSwitch(node) => {
2323 offsets.insert((instruction.offset as i32 + node.default_offset) as u16);
2324 for (_, offset) in &node.pairs {
2325 offsets.insert((instruction.offset as i32 + *offset) as u16);
2326 }
2327 }
2328 _ => {}
2329 }
2330 }
2331 for entry in exception_table {
2332 offsets.insert(entry.start_pc);
2333 offsets.insert(entry.end_pc);
2334 offsets.insert(entry.handler_pc);
2335 }
2336 offsets.insert(code.len() as u16);
2337
2338 let mut label_by_offset = std::collections::HashMap::new();
2339 for (next_id, offset) in offsets.into_iter().enumerate() {
2340 label_by_offset.insert(offset, LabelNode { id: next_id });
2341 }
2342
2343 let mut nodes = Vec::new();
2344 for instruction in instructions {
2345 if let Some(label) = label_by_offset.get(&{ instruction.offset }) {
2346 nodes.push(AbstractInsnNode::Label(*label));
2347 }
2348 nodes.push(AbstractInsnNode::Insn(instruction.insn));
2349 }
2350 if let Some(label) = label_by_offset.get(&(code.len() as u16)) {
2351 nodes.push(AbstractInsnNode::Label(*label));
2352 }
2353
2354 let mut try_catch_blocks = Vec::new();
2355 for entry in exception_table {
2356 let start = *label_by_offset
2357 .get(&entry.start_pc)
2358 .ok_or_else(|| ClassReadError::InvalidAttribute("missing start label".to_string()))?;
2359 let end = *label_by_offset
2360 .get(&entry.end_pc)
2361 .ok_or_else(|| ClassReadError::InvalidAttribute("missing end label".to_string()))?;
2362 let handler = *label_by_offset
2363 .get(&entry.handler_pc)
2364 .ok_or_else(|| ClassReadError::InvalidAttribute("missing handler label".to_string()))?;
2365 let catch_type = if entry.catch_type == 0 {
2366 None
2367 } else {
2368 Some(cp_class_name(cp, entry.catch_type)?.to_string())
2369 };
2370 try_catch_blocks.push(TryCatchBlockNode {
2371 start,
2372 end,
2373 handler,
2374 catch_type,
2375 });
2376 }
2377
2378 Ok((nodes, try_catch_blocks, label_by_offset))
2379}
2380
2381pub(crate) fn build_insn_nodes_public(
2382 code: &[u8],
2383 exception_table: &[ExceptionTableEntry],
2384 cp: &[CpInfo],
2385) -> Result<(Vec<AbstractInsnNode>, Vec<TryCatchBlockNode>), ClassReadError> {
2386 let (nodes, try_catch_blocks, _) = build_insn_nodes(code, exception_table, cp)?;
2387 Ok((nodes, try_catch_blocks))
2388}
2389
2390fn attach_line_numbers(
2391 nodes: Vec<AbstractInsnNode>,
2392 entries: &[LineNumber],
2393 label_by_offset: &std::collections::HashMap<u16, LabelNode>,
2394) -> Vec<AbstractInsnNode> {
2395 let mut lines_by_label = std::collections::HashMap::<usize, Vec<LineNumberInsnNode>>::new();
2396 for entry in entries {
2397 if let Some(label) = label_by_offset.get(&entry.start_pc) {
2398 lines_by_label
2399 .entry(label.id)
2400 .or_default()
2401 .push(LineNumberInsnNode {
2402 line: entry.line_number,
2403 start: *label,
2404 });
2405 }
2406 }
2407
2408 let mut merged = Vec::with_capacity(nodes.len() + entries.len());
2409 for node in nodes {
2410 let label_id = match &node {
2411 AbstractInsnNode::Label(label) => Some(label.id),
2412 _ => None,
2413 };
2414 merged.push(node);
2415 if let Some(label_id) = label_id
2416 && let Some(lines) = lines_by_label.remove(&label_id)
2417 {
2418 for line in lines {
2419 merged.push(AbstractInsnNode::LineNumber(line));
2420 }
2421 }
2422 }
2423 merged
2424}
2425
2426fn read_table_switch(
2427 reader: &mut ByteReader<'_>,
2428 opcode_offset: usize,
2429) -> Result<Insn, ClassReadError> {
2430 reader.align4(opcode_offset)?;
2431 let default_offset = reader.read_i4()?;
2432 let low = reader.read_i4()?;
2433 let high = reader.read_i4()?;
2434 let count = if high < low {
2435 0
2436 } else {
2437 (high - low + 1) as usize
2438 };
2439 let mut offsets = Vec::with_capacity(count);
2440 for _ in 0..count {
2441 offsets.push(reader.read_i4()?);
2442 }
2443 Ok(Insn::TableSwitch(TableSwitchInsnNode {
2444 insn: opcodes::TABLESWITCH.into(),
2445 default_offset,
2446 low,
2447 high,
2448 offsets,
2449 }))
2450}
2451
2452fn read_lookup_switch(
2453 reader: &mut ByteReader<'_>,
2454 opcode_offset: usize,
2455) -> Result<Insn, ClassReadError> {
2456 reader.align4(opcode_offset)?;
2457 let default_offset = reader.read_i4()?;
2458 let npairs = reader.read_i4()? as usize;
2459 let mut pairs = Vec::with_capacity(npairs);
2460 for _ in 0..npairs {
2461 let key = reader.read_i4()?;
2462 let offset = reader.read_i4()?;
2463 pairs.push((key, offset));
2464 }
2465 Ok(Insn::LookupSwitch(LookupSwitchInsnNode {
2466 insn: opcodes::LOOKUPSWITCH.into(),
2467 default_offset,
2468 pairs,
2469 }))
2470}
2471
2472fn read_wide(reader: &mut ByteReader<'_>) -> Result<Insn, ClassReadError> {
2473 let opcode = reader.read_u1()?;
2474 match opcode {
2475 opcodes::ILOAD..=opcodes::ALOAD | opcodes::ISTORE..=opcodes::ASTORE | opcodes::RET => {
2476 Ok(Insn::Var(VarInsnNode {
2477 insn: opcode.into(),
2478 var_index: reader.read_u2()?,
2479 }))
2480 }
2481 opcodes::IINC => Ok(Insn::Iinc(IincInsnNode {
2482 insn: opcode.into(),
2483 var_index: reader.read_u2()?,
2484 increment: reader.read_i2()?,
2485 })),
2486 _ => Err(ClassReadError::InvalidOpcode {
2487 opcode,
2488 offset: reader.pos().saturating_sub(1),
2489 }),
2490 }
2491}
2492
2493fn visit_instruction(
2494 cp: &[CpInfo],
2495 offset: i32,
2496 insn: Insn,
2497 mv: &mut dyn MethodVisitor,
2498) -> Result<(), ClassReadError> {
2499 match insn {
2500 Insn::Simple(node) => {
2501 mv.visit_insn(node.opcode);
2502 }
2503 Insn::Int(node) => {
2504 mv.visit_int_insn(node.insn.opcode, node.operand);
2505 }
2506 Insn::Var(node) => {
2507 mv.visit_var_insn(node.insn.opcode, node.var_index);
2508 }
2509 Insn::Type(node) => {
2510 let type_name = cp_class_name(cp, node.type_index)?;
2511 mv.visit_type_insn(node.insn.opcode, type_name);
2512 }
2513 Insn::Field(node) => {
2514 let index = match node.field_ref {
2515 MemberRef::Index(index) => index,
2516 MemberRef::Symbolic { .. } => {
2517 return Err(ClassReadError::InvalidIndex(0));
2518 }
2519 };
2520 let (owner, name, desc) = cp_field_ref(cp, index)?;
2521 mv.visit_field_insn(node.insn.opcode, owner, name, desc);
2522 }
2523 Insn::Method(node) => {
2524 let index = match node.method_ref {
2525 MemberRef::Index(index) => index,
2526 MemberRef::Symbolic { .. } => {
2527 return Err(ClassReadError::InvalidIndex(0));
2528 }
2529 };
2530 let (owner, name, desc, is_interface) = cp_method_ref(cp, index)?;
2531 mv.visit_method_insn(node.insn.opcode, owner, name, desc, is_interface);
2532 }
2533 Insn::InvokeInterface(node) => {
2534 let (owner, name, desc, _is_interface) = cp_method_ref(cp, node.method_index)?;
2535 mv.visit_method_insn(node.insn.opcode, owner, name, desc, true);
2536 }
2537 Insn::InvokeDynamic(node) => {
2538 let (name, desc) = cp_invoke_dynamic(cp, node.method_index)?;
2539 mv.visit_invoke_dynamic_insn(name, desc);
2540 }
2541 Insn::Jump(node) => {
2542 let target = offset + node.offset;
2543 mv.visit_jump_insn(node.insn.opcode, target);
2544 }
2545 Insn::Ldc(node) => {
2546 let index = match node.value {
2547 LdcValue::Index(index) => index,
2548 LdcValue::String(value) => {
2549 mv.visit_ldc_insn(LdcConstant::String(value));
2550 return Ok(());
2551 }
2552 LdcValue::Type(value) => {
2553 match value.clone() {
2554 Type::Method { .. } => {
2555 mv.visit_ldc_insn(LdcConstant::MethodType(value.get_descriptor()));
2556 }
2557 _ => {
2558 mv.visit_ldc_insn(LdcConstant::Class(value.get_descriptor()));
2559 }
2560 }
2561
2562 return Ok(());
2563 }
2564 LdcValue::Int(value) => {
2565 mv.visit_ldc_insn(LdcConstant::Integer(value));
2566 return Ok(());
2567 }
2568 LdcValue::Float(value) => {
2569 mv.visit_ldc_insn(LdcConstant::Float(value));
2570 return Ok(());
2571 }
2572 LdcValue::Long(value) => {
2573 mv.visit_ldc_insn(LdcConstant::Long(value));
2574 return Ok(());
2575 }
2576 LdcValue::Double(value) => {
2577 mv.visit_ldc_insn(LdcConstant::Double(value));
2578 return Ok(());
2579 }
2580 };
2581 let constant = cp_ldc_constant(cp, index)?;
2582 mv.visit_ldc_insn(constant);
2583 }
2584 Insn::Iinc(node) => {
2585 mv.visit_iinc_insn(node.var_index, node.increment);
2586 }
2587 Insn::TableSwitch(node) => {
2588 let targets = node
2589 .offsets
2590 .iter()
2591 .map(|value| offset + *value)
2592 .collect::<Vec<_>>();
2593 mv.visit_table_switch(offset + node.default_offset, node.low, node.high, &targets);
2594 }
2595 Insn::LookupSwitch(node) => {
2596 let pairs = node
2597 .pairs
2598 .iter()
2599 .map(|(key, value)| (*key, offset + *value))
2600 .collect::<Vec<_>>();
2601 mv.visit_lookup_switch(offset + node.default_offset, &pairs);
2602 }
2603 Insn::MultiANewArray(node) => {
2604 let type_name = cp_class_name(cp, node.type_index)?;
2605 mv.visit_multi_anewarray_insn(type_name, node.dimensions);
2606 }
2607 }
2608 Ok(())
2609}
2610
2611pub struct ByteReader<'a> {
2612 data: &'a [u8],
2613 pos: usize,
2614}
2615
2616impl<'a> ByteReader<'a> {
2617 pub fn new(data: &'a [u8]) -> Self {
2618 Self { data, pos: 0 }
2619 }
2620
2621 pub fn remaining(&self) -> usize {
2622 self.data.len().saturating_sub(self.pos)
2623 }
2624
2625 pub fn pos(&self) -> usize {
2626 self.pos
2627 }
2628
2629 pub fn align4(&mut self, opcode_offset: usize) -> Result<(), ClassReadError> {
2630 let mut padding = (4 - ((opcode_offset + 1) % 4)) % 4;
2631 while padding > 0 {
2632 self.read_u1()?;
2633 padding -= 1;
2634 }
2635 Ok(())
2636 }
2637
2638 pub fn read_u1(&mut self) -> Result<u8, ClassReadError> {
2639 if self.pos >= self.data.len() {
2640 return Err(ClassReadError::UnexpectedEof);
2641 }
2642 let value = self.data[self.pos];
2643 self.pos += 1;
2644 Ok(value)
2645 }
2646
2647 pub fn read_i1(&mut self) -> Result<i8, ClassReadError> {
2648 Ok(self.read_u1()? as i8)
2649 }
2650
2651 pub fn read_u2(&mut self) -> Result<u16, ClassReadError> {
2652 let bytes = self.read_bytes(2)?;
2653 Ok(u16::from_be_bytes([bytes[0], bytes[1]]))
2654 }
2655
2656 pub fn read_i2(&mut self) -> Result<i16, ClassReadError> {
2657 Ok(self.read_u2()? as i16)
2658 }
2659
2660 pub fn read_u4(&mut self) -> Result<u32, ClassReadError> {
2661 let bytes = self.read_bytes(4)?;
2662 Ok(u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
2663 }
2664
2665 pub fn read_i4(&mut self) -> Result<i32, ClassReadError> {
2666 let bytes = self.read_bytes(4)?;
2667 Ok(i32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
2668 }
2669
2670 pub fn read_u8(&mut self) -> Result<u64, ClassReadError> {
2671 let bytes = self.read_bytes(8)?;
2672 Ok(u64::from_be_bytes([
2673 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
2674 ]))
2675 }
2676
2677 pub fn read_bytes(&mut self, len: usize) -> Result<Vec<u8>, ClassReadError> {
2678 if self.pos + len > self.data.len() {
2679 return Err(ClassReadError::UnexpectedEof);
2680 }
2681 let bytes = self.data[self.pos..self.pos + len].to_vec();
2682 self.pos += len;
2683 Ok(bytes)
2684 }
2685}
2686
2687#[cfg(test)]
2688mod tests {
2689 use crate::class_writer::ClassWriter;
2690 use crate::constants::*;
2691 use crate::insn::{Label, LabelNode};
2692 use crate::opcodes;
2693
2694 use super::*;
2695 use std::cell::RefCell;
2696 use std::rc::Rc;
2697
2698 struct MockClassVisitor {
2700 pub visited_name: Rc<RefCell<Option<String>>>,
2701 pub visited_methods: Rc<RefCell<Vec<String>>>,
2702 }
2703
2704 impl MockClassVisitor {
2705 fn new() -> Self {
2706 Self {
2707 visited_name: Rc::new(RefCell::new(None)),
2708 visited_methods: Rc::new(RefCell::new(Vec::new())),
2709 }
2710 }
2711 }
2712
2713 impl ClassVisitor for MockClassVisitor {
2714 fn visit(
2715 &mut self,
2716 _major: u16,
2717 _minor: u16,
2718 _access_flags: u16,
2719 name: &str,
2720 _super_name: Option<&str>,
2721 _interfaces: &[String],
2722 ) {
2723 *self.visited_name.borrow_mut() = Some(name.to_string());
2724 }
2725
2726 fn visit_method(
2727 &mut self,
2728 _access_flags: u16,
2729 name: &str,
2730 _descriptor: &str,
2731 ) -> Option<Box<dyn MethodVisitor>> {
2732 self.visited_methods.borrow_mut().push(name.to_string());
2733 None
2734 }
2735 }
2736
2737 fn generate_minimal_class() -> Vec<u8> {
2740 let mut w = Vec::new();
2741 w.extend_from_slice(&0xCAFEBABE_u32.to_be_bytes());
2743 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);
2756 let name = "TestClass";
2757 w.extend_from_slice(&(name.len() as u16).to_be_bytes());
2758 w.extend_from_slice(name.as_bytes());
2759
2760 w.push(7);
2762 w.extend_from_slice(&1_u16.to_be_bytes());
2763
2764 w.push(1);
2766 let obj = "java/lang/Object";
2767 w.extend_from_slice(&(obj.len() as u16).to_be_bytes());
2768 w.extend_from_slice(obj.as_bytes());
2769
2770 w.push(7);
2772 w.extend_from_slice(&3_u16.to_be_bytes());
2773
2774 w.extend_from_slice(&0x0021_u16.to_be_bytes());
2776 w.extend_from_slice(&2_u16.to_be_bytes());
2778 w.extend_from_slice(&4_u16.to_be_bytes());
2780
2781 w.extend_from_slice(&0_u16.to_be_bytes());
2783 w.extend_from_slice(&0_u16.to_be_bytes());
2785 w.extend_from_slice(&0_u16.to_be_bytes());
2787 w.extend_from_slice(&0_u16.to_be_bytes());
2789
2790 w
2791 }
2792
2793 fn generate_module_info_class() -> Vec<u8> {
2794 let mut writer = ClassWriter::new(0);
2795 writer.visit(V9, 0, ACC_MODULE, "module-info", None, &[]);
2796
2797 let mut module = writer.visit_module("com.example.app", ACC_OPEN, Some("1.0"));
2798 module.visit_main_class("com/example/app/Main");
2799 module.visit_package("com/example/api");
2800 module.visit_package("com/example/internal");
2801 module.visit_require("java.base", ACC_MANDATED, None);
2802 module.visit_require(
2803 "com.example.lib",
2804 ACC_TRANSITIVE | ACC_STATIC_PHASE,
2805 Some("2.1"),
2806 );
2807 module.visit_export("com/example/api", 0, &["com.example.consumer"]);
2808 module.visit_open("com/example/internal", 0, &["com.example.runtime"]);
2809 module.visit_use("com/example/spi/Service");
2810 module.visit_provide("com/example/spi/Service", &["com/example/impl/ServiceImpl"]);
2811 module.visit_end(&mut writer);
2812
2813 writer.to_bytes().expect("module-info should encode")
2814 }
2815
2816 #[test]
2817 fn test_class_reader_header() {
2818 let bytes = generate_minimal_class();
2819 let reader = ClassReader::new(&bytes);
2820 let mut visitor = MockClassVisitor::new();
2821
2822 let result = reader.accept(&mut visitor, 0);
2823
2824 assert!(result.is_ok(), "Should parse valid class file");
2825 assert_eq!(
2826 *visitor.visited_name.borrow(),
2827 Some("TestClass".to_string())
2828 );
2829 }
2830
2831 #[test]
2832 fn test_invalid_magic() {
2833 let bytes = vec![0x00, 0x00, 0x00, 0x00];
2835 let reader = ClassReader::new(&bytes);
2836 let mut visitor = MockClassVisitor::new();
2837
2838 let result = reader.accept(&mut visitor, 0);
2839 assert!(matches!(result, Err(ClassReadError::InvalidMagic(_))));
2840 }
2841
2842 #[test]
2843 fn test_code_reader_alignment() {
2844 let data = vec![0x00, 0x00, 0x00, 0x00]; let mut reader = super::ByteReader::new(&data);
2847
2848 reader.pos = 1;
2850 assert!(reader.align4(0).is_ok());
2852 assert_eq!(reader.pos(), 4);
2853 }
2854
2855 #[test]
2856 fn test_parse_runtime_visible_type_annotations_supertype() {
2857 let mut info = vec![];
2867 u2(1, &mut info);
2868 u1(TA_TARGET_CLASS_EXTENDS, &mut info);
2869 u2(5, &mut info);
2870 u1(0, &mut info);
2871 u2(10, &mut info);
2872 u2(0, &mut info);
2873
2874 let cp: Vec<CpInfo> = vec![];
2875 let attr = parse_attribute("RuntimeVisibleTypeAnnotations", info, &cp).unwrap();
2876
2877 match attr {
2878 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations } => {
2879 assert_eq!(annotations.len(), 1);
2880 let a = &annotations[0];
2881 assert_eq!(a.target_type, TA_TARGET_CLASS_EXTENDS);
2882 assert!(matches!(
2883 a.target_info,
2884 TypeAnnotationTargetInfo::Supertype { supertype_index: 5 }
2885 ));
2886 assert_eq!(a.target_path.path.len(), 0);
2887 assert_eq!(a.annotation.type_descriptor_index, 10);
2888 assert_eq!(a.annotation.element_value_pairs.len(), 0);
2889 }
2890 other => panic!("unexpected attr: {:?}", other),
2891 }
2892 }
2893
2894 #[test]
2895 fn test_parse_runtime_visible_type_annotations_formal_parameter_with_path() {
2896 let mut info = vec![];
2901 u2(1, &mut info);
2902 u1(TA_TARGET_METHOD_FORMAL_PARAMETER, &mut info);
2903 u1(2, &mut info);
2904
2905 u1(1, &mut info); u1(TA_TYPE_PATH_ARRAY, &mut info);
2907 u1(0, &mut info);
2908
2909 u2(9, &mut info);
2910 u2(0, &mut info);
2911
2912 let cp: Vec<CpInfo> = vec![];
2913 let attr = parse_attribute("RuntimeVisibleTypeAnnotations", info, &cp).unwrap();
2914
2915 match attr {
2916 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations } => {
2917 let a = &annotations[0];
2918 assert_eq!(a.target_type, TA_TARGET_METHOD_FORMAL_PARAMETER);
2919 assert!(matches!(
2920 a.target_info,
2921 TypeAnnotationTargetInfo::FormalParameter {
2922 formal_parameter_index: 2
2923 }
2924 ));
2925 assert_eq!(a.target_path.path.len(), 1);
2926 assert_eq!(a.target_path.path[0].type_path_kind, TA_TYPE_PATH_ARRAY);
2927 assert_eq!(a.target_path.path[0].type_argument_index, 0);
2928 }
2929 other => panic!("unexpected attr: {:?}", other),
2930 }
2931 }
2932
2933 #[test]
2934 fn test_parse_runtime_visible_type_annotations_localvar_table() {
2935 let mut info = vec![];
2941 u2(1, &mut info);
2942 u1(TA_TARGET_LOCAL_VARIABLE, &mut info);
2943
2944 u2(1, &mut info); u2(1, &mut info);
2946 u2(2, &mut info);
2947 u2(3, &mut info);
2948
2949 u1(0, &mut info); u2(8, &mut info);
2951 u2(0, &mut info);
2952
2953 let cp: Vec<CpInfo> = vec![];
2954 let attr = parse_attribute("RuntimeVisibleTypeAnnotations", info, &cp).unwrap();
2955
2956 match attr {
2957 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations } => {
2958 let a = &annotations[0];
2959 assert_eq!(a.target_type, TA_TARGET_LOCAL_VARIABLE);
2960 match &a.target_info {
2961 TypeAnnotationTargetInfo::LocalVar { table } => {
2962 assert_eq!(table.len(), 1);
2963 assert_eq!(table[0].start_pc, 1);
2964 assert_eq!(table[0].length, 2);
2965 assert_eq!(table[0].index, 3);
2966 }
2967 other => panic!("unexpected target_info: {:?}", other),
2968 }
2969 }
2970 other => panic!("unexpected attr: {:?}", other),
2971 }
2972 }
2973
2974 #[test]
2975 fn test_parse_module_attribute_family() {
2976 let mut module_info = vec![];
2977 u2(1, &mut module_info);
2978 u2(ACC_OPEN, &mut module_info);
2979 u2(2, &mut module_info);
2980 u2(1, &mut module_info);
2981 u2(3, &mut module_info);
2982 u2(ACC_TRANSITIVE | ACC_STATIC_PHASE, &mut module_info);
2983 u2(4, &mut module_info);
2984 u2(1, &mut module_info);
2985 u2(5, &mut module_info);
2986 u2(ACC_MANDATED, &mut module_info);
2987 u2(2, &mut module_info);
2988 u2(6, &mut module_info);
2989 u2(7, &mut module_info);
2990 u2(1, &mut module_info);
2991 u2(8, &mut module_info);
2992 u2(0, &mut module_info);
2993 u2(1, &mut module_info);
2994 u2(9, &mut module_info);
2995 u2(1, &mut module_info);
2996 u2(10, &mut module_info);
2997 u2(1, &mut module_info);
2998 u2(11, &mut module_info);
2999 u2(2, &mut module_info);
3000 u2(12, &mut module_info);
3001 u2(13, &mut module_info);
3002
3003 let attr = parse_attribute("Module", module_info, &[]).expect("module attr should parse");
3004 match attr {
3005 AttributeInfo::Module(module) => {
3006 assert_eq!(module.module_name_index, 1);
3007 assert_eq!(module.module_flags, ACC_OPEN);
3008 assert_eq!(module.module_version_index, 2);
3009 assert_eq!(
3010 module.requires,
3011 vec![ModuleRequire {
3012 requires_index: 3,
3013 requires_flags: ACC_TRANSITIVE | ACC_STATIC_PHASE,
3014 requires_version_index: 4,
3015 }]
3016 );
3017 assert_eq!(
3018 module.exports,
3019 vec![ModuleExport {
3020 exports_index: 5,
3021 exports_flags: ACC_MANDATED,
3022 exports_to_index: vec![6, 7],
3023 }]
3024 );
3025 assert_eq!(
3026 module.opens,
3027 vec![ModuleOpen {
3028 opens_index: 8,
3029 opens_flags: 0,
3030 opens_to_index: vec![9],
3031 }]
3032 );
3033 assert_eq!(module.uses_index, vec![10]);
3034 assert_eq!(
3035 module.provides,
3036 vec![ModuleProvide {
3037 provides_index: 11,
3038 provides_with_index: vec![12, 13],
3039 }]
3040 );
3041 }
3042 other => panic!("unexpected attr: {:?}", other),
3043 }
3044
3045 let mut packages_info = vec![];
3046 u2(2, &mut packages_info);
3047 u2(21, &mut packages_info);
3048 u2(22, &mut packages_info);
3049 let attr = parse_attribute("ModulePackages", packages_info, &[])
3050 .expect("module packages attr should parse");
3051 match attr {
3052 AttributeInfo::ModulePackages {
3053 package_index_table,
3054 } => {
3055 assert_eq!(package_index_table, vec![21, 22]);
3056 }
3057 other => panic!("unexpected attr: {:?}", other),
3058 }
3059
3060 let mut main_class_info = vec![];
3061 u2(23, &mut main_class_info);
3062 let attr = parse_attribute("ModuleMainClass", main_class_info, &[])
3063 .expect("module main class attr should parse");
3064 match attr {
3065 AttributeInfo::ModuleMainClass { main_class_index } => {
3066 assert_eq!(main_class_index, 23);
3067 }
3068 other => panic!("unexpected attr: {:?}", other),
3069 }
3070 }
3071
3072 fn u1(v: u8, out: &mut Vec<u8>) {
3073 out.push(v);
3074 }
3075 fn u2(v: u16, out: &mut Vec<u8>) {
3076 out.extend_from_slice(&v.to_be_bytes());
3077 }
3078
3079 #[test]
3080 fn test_method_node_contains_offsets_and_line_numbers() {
3081 let mut writer = ClassWriter::new(0);
3082 writer.visit(
3083 52,
3084 0,
3085 ACC_PUBLIC,
3086 "TestNodeData",
3087 Some("java/lang/Object"),
3088 &[],
3089 );
3090
3091 let mut ctor = writer.visit_method(ACC_PUBLIC, "<init>", "()V");
3092 ctor.visit_code();
3093 ctor.visit_var_insn(opcodes::ALOAD, 0);
3094 ctor.visit_method_insn(
3095 opcodes::INVOKESPECIAL,
3096 "java/lang/Object",
3097 "<init>",
3098 "()V",
3099 false,
3100 );
3101 ctor.visit_insn(opcodes::RETURN);
3102 ctor.visit_maxs(1, 1);
3103 ctor.visit_end(&mut writer);
3104
3105 let mut method = writer.visit_method(ACC_PUBLIC | ACC_STATIC, "answer", "()I");
3106 let start = Label::new();
3107 method.visit_code();
3108 method.visit_label(start);
3109 method.visit_line_number(123, LabelNode::from_label(start));
3110 method.visit_insn(opcodes::ICONST_1);
3111 method.visit_insn(opcodes::IRETURN);
3112 method.visit_maxs(1, 0);
3113 method.visit_end(&mut writer);
3114
3115 let bytes = writer.to_bytes().expect("class should encode");
3116 let class = ClassReader::new(&bytes)
3117 .to_class_node()
3118 .expect("class should decode");
3119 let method = class
3120 .methods
3121 .iter()
3122 .find(|method| method.name == "answer")
3123 .expect("method should exist");
3124
3125 assert_eq!(method.instruction_offsets, vec![0, 1]);
3126 assert_eq!(method.line_numbers.len(), 1);
3127 assert_eq!(method.line_numbers[0].line_number, 123);
3128 assert!(
3129 method
3130 .insn_nodes
3131 .iter()
3132 .any(|node| matches!(node, AbstractInsnNode::LineNumber(_)))
3133 );
3134 assert!(
3135 method
3136 .insn_nodes
3137 .iter()
3138 .any(|node| matches!(node, AbstractInsnNode::Label(_)))
3139 );
3140 assert!(method.try_catch_blocks.is_empty());
3141 }
3142
3143 #[test]
3144 fn test_method_node_contains_try_catch_blocks() {
3145 let mut writer = ClassWriter::new(0);
3146 writer.visit(
3147 52,
3148 0,
3149 ACC_PUBLIC,
3150 "TestTryCatchNode",
3151 Some("java/lang/Object"),
3152 &[],
3153 );
3154
3155 let mut ctor = writer.visit_method(ACC_PUBLIC, "<init>", "()V");
3156 ctor.visit_code();
3157 ctor.visit_var_insn(opcodes::ALOAD, 0);
3158 ctor.visit_method_insn(
3159 opcodes::INVOKESPECIAL,
3160 "java/lang/Object",
3161 "<init>",
3162 "()V",
3163 false,
3164 );
3165 ctor.visit_insn(opcodes::RETURN);
3166 ctor.visit_maxs(1, 1);
3167 ctor.visit_end(&mut writer);
3168
3169 let start = Label::new();
3170 let end = Label::new();
3171 let handler = Label::new();
3172 let mut method =
3173 writer.visit_method(ACC_PUBLIC | ACC_STATIC, "safeLen", "(Ljava/lang/String;)I");
3174 method.visit_code();
3175 method.visit_label(start);
3176 method.visit_var_insn(opcodes::ALOAD, 0);
3177 method.visit_method_insn(
3178 opcodes::INVOKEVIRTUAL,
3179 "java/lang/String",
3180 "length",
3181 "()I",
3182 false,
3183 );
3184 method.visit_insn(opcodes::IRETURN);
3185 method.visit_label(end);
3186 method.visit_label(handler);
3187 method.visit_var_insn(opcodes::ASTORE, 1);
3188 method.visit_insn(opcodes::ICONST_M1);
3189 method.visit_insn(opcodes::IRETURN);
3190 method.visit_try_catch_block(start, end, handler, Some("java/lang/RuntimeException"));
3191 method.visit_maxs(1, 2);
3192 method.visit_end(&mut writer);
3193
3194 let bytes = writer.to_bytes().expect("class should encode");
3195 let class = ClassReader::new(&bytes)
3196 .to_class_node()
3197 .expect("class should decode");
3198 let method = class
3199 .methods
3200 .iter()
3201 .find(|method| method.name == "safeLen")
3202 .expect("method should exist");
3203
3204 assert_eq!(method.exception_table.len(), 1);
3205 assert_eq!(method.try_catch_blocks.len(), 1);
3206 assert_eq!(
3207 method.try_catch_blocks[0].catch_type.as_deref(),
3208 Some("java/lang/RuntimeException")
3209 );
3210 }
3211
3212 #[test]
3213 fn test_parse_runtime_visible_annotations_one_empty() {
3214 let mut info = vec![];
3217 u2(1, &mut info);
3218 u2(10, &mut info);
3219 u2(0, &mut info);
3220
3221 let cp: Vec<CpInfo> = vec![];
3222 let attr = parse_attribute("RuntimeVisibleAnnotations", info, &cp).unwrap();
3223 match attr {
3224 AttributeInfo::RuntimeVisibleAnnotations { annotations } => {
3225 assert_eq!(annotations.len(), 1);
3226 assert_eq!(annotations[0].type_descriptor_index, 10);
3227 assert_eq!(annotations[0].element_value_pairs.len(), 0);
3228 }
3229 other => panic!("unexpected attr: {:?}", other),
3230 }
3231 }
3232
3233 #[test]
3234 fn test_parse_runtime_visible_parameter_annotations_two_params() {
3235 let mut info = vec![];
3239 u1(2, &mut info);
3240 u2(1, &mut info);
3241 u2(10, &mut info);
3242 u2(0, &mut info);
3243 u2(0, &mut info);
3244
3245 let cp: Vec<CpInfo> = vec![];
3246 let attr = parse_attribute("RuntimeVisibleParameterAnnotations", info, &cp).unwrap();
3247 match attr {
3248 AttributeInfo::RuntimeVisibleParameterAnnotations { parameters } => {
3249 assert_eq!(parameters.parameters.len(), 2);
3250 assert_eq!(parameters.parameters[0].len(), 1);
3251 assert_eq!(parameters.parameters[1].len(), 0);
3252 }
3253 other => panic!("unexpected attr: {:?}", other),
3254 }
3255 }
3256
3257 #[test]
3258 fn test_class_reader_decodes_module_info_node() {
3259 let bytes = generate_module_info_class();
3260 let class = ClassReader::new(&bytes)
3261 .to_class_node()
3262 .expect("module-info should decode");
3263
3264 assert_eq!(class.name, "module-info");
3265 assert_eq!(class.access_flags, ACC_MODULE);
3266
3267 let module = class.module.expect("module descriptor should be decoded");
3268 assert_eq!(module.name, "com.example.app");
3269 assert_eq!(module.access_flags, ACC_OPEN);
3270 assert_eq!(module.version.as_deref(), Some("1.0"));
3271 assert_eq!(module.main_class.as_deref(), Some("com/example/app/Main"));
3272 assert_eq!(
3273 module.packages,
3274 vec![
3275 "com/example/api".to_string(),
3276 "com/example/internal".to_string()
3277 ]
3278 );
3279 assert_eq!(module.requires.len(), 2);
3280 assert_eq!(module.requires[0].module, "java.base");
3281 assert_eq!(module.requires[0].access_flags, ACC_MANDATED);
3282 assert_eq!(module.requires[0].version, None);
3283 assert_eq!(module.requires[1].module, "com.example.lib");
3284 assert_eq!(
3285 module.requires[1].access_flags,
3286 ACC_TRANSITIVE | ACC_STATIC_PHASE
3287 );
3288 assert_eq!(module.requires[1].version.as_deref(), Some("2.1"));
3289 assert_eq!(module.exports.len(), 1);
3290 assert_eq!(module.exports[0].package, "com/example/api");
3291 assert_eq!(
3292 module.exports[0].modules,
3293 vec!["com.example.consumer".to_string()]
3294 );
3295 assert_eq!(module.opens.len(), 1);
3296 assert_eq!(module.opens[0].package, "com/example/internal");
3297 assert_eq!(
3298 module.opens[0].modules,
3299 vec!["com.example.runtime".to_string()]
3300 );
3301 assert_eq!(module.uses, vec!["com/example/spi/Service".to_string()]);
3302 assert_eq!(module.provides.len(), 1);
3303 assert_eq!(module.provides[0].service, "com/example/spi/Service");
3304 assert_eq!(
3305 module.provides[0].providers,
3306 vec!["com/example/impl/ServiceImpl".to_string()]
3307 );
3308 }
3309}