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 Ok(crate::nodes::ClassNode {
780 minor_version: self.minor_version,
781 major_version: self.major_version,
782 access_flags: self.access_flags,
783 constant_pool: self.constant_pool.clone(),
784 this_class: self.this_class,
785 name,
786 super_name,
787 source_file,
788 interfaces,
789 interface_indices: self.interfaces.clone(),
790 fields,
791 methods,
792 attributes: self.attributes.clone(),
793 inner_classes,
794 outer_class,
795 module,
796 })
797 }
798}
799
800#[derive(Debug, Clone)]
801pub struct FieldInfo {
802 pub access_flags: u16,
803 pub name_index: u16,
804 pub descriptor_index: u16,
805 pub attributes: Vec<AttributeInfo>,
806}
807
808#[derive(Debug, Clone)]
809pub struct MethodInfo {
810 pub access_flags: u16,
811 pub name_index: u16,
812 pub descriptor_index: u16,
813 pub attributes: Vec<AttributeInfo>,
814}
815
816#[derive(Debug, Clone)]
817pub enum AttributeInfo {
818 Code(CodeAttribute),
819 ConstantValue { constantvalue_index: u16 },
820 Exceptions { exception_index_table: Vec<u16> },
821 SourceFile { sourcefile_index: u16 },
822 LineNumberTable { entries: Vec<LineNumber> },
823 LocalVariableTable { entries: Vec<LocalVariable> },
824 Signature { signature_index: u16 },
825 StackMapTable { entries: Vec<StackMapFrame> },
826 Deprecated,
827 Synthetic,
828 InnerClasses { classes: Vec<InnerClass> },
829 EnclosingMethod { class_index: u16, method_index: u16 },
830 Module(ModuleAttribute),
831 ModulePackages { package_index_table: Vec<u16> },
832 ModuleMainClass { main_class_index: u16 },
833 BootstrapMethods { methods: Vec<BootstrapMethod> },
834 MethodParameters { parameters: Vec<MethodParameter> },
835 RuntimeVisibleAnnotations { annotations: Vec<Annotation> },
836 RuntimeInvisibleAnnotations { annotations: Vec<Annotation> },
837 RuntimeVisibleParameterAnnotations { parameters: ParameterAnnotations },
838 RuntimeInvisibleParameterAnnotations { parameters: ParameterAnnotations },
839 RuntimeVisibleTypeAnnotations { annotations: Vec<TypeAnnotation> },
840 RuntimeInvisibleTypeAnnotations { annotations: Vec<TypeAnnotation> },
841 Unknown { name: String, info: Vec<u8> },
842}
843
844#[derive(Debug, Clone, PartialEq, Eq)]
845pub struct ModuleAttribute {
846 pub module_name_index: u16,
847 pub module_flags: u16,
848 pub module_version_index: u16,
849 pub requires: Vec<ModuleRequire>,
850 pub exports: Vec<ModuleExport>,
851 pub opens: Vec<ModuleOpen>,
852 pub uses_index: Vec<u16>,
853 pub provides: Vec<ModuleProvide>,
854}
855
856#[derive(Debug, Clone, PartialEq, Eq)]
857pub struct ModuleRequire {
858 pub requires_index: u16,
859 pub requires_flags: u16,
860 pub requires_version_index: u16,
861}
862
863#[derive(Debug, Clone, PartialEq, Eq)]
864pub struct ModuleExport {
865 pub exports_index: u16,
866 pub exports_flags: u16,
867 pub exports_to_index: Vec<u16>,
868}
869
870#[derive(Debug, Clone, PartialEq, Eq)]
871pub struct ModuleOpen {
872 pub opens_index: u16,
873 pub opens_flags: u16,
874 pub opens_to_index: Vec<u16>,
875}
876
877#[derive(Debug, Clone, PartialEq, Eq)]
878pub struct ModuleProvide {
879 pub provides_index: u16,
880 pub provides_with_index: Vec<u16>,
881}
882
883#[derive(Debug, Clone, PartialEq)]
884pub struct Annotation {
885 pub type_descriptor_index: u16,
886 pub element_value_pairs: Vec<ElementValuePair>,
887}
888
889#[derive(Debug, Clone, PartialEq)]
890pub struct ElementValuePair {
891 pub element_name_index: u16,
892 pub value: ElementValue,
893}
894
895#[derive(Debug, Clone, PartialEq)]
896pub enum ElementValue {
897 ConstValueIndex {
898 tag: u8,
899 const_value_index: u16,
900 },
901 EnumConstValue {
902 type_name_index: u16,
903 const_name_index: u16,
904 },
905 ClassInfoIndex {
906 class_info_index: u16,
907 },
908 AnnotationValue(Box<Annotation>),
909 ArrayValue(Vec<ElementValue>),
910}
911
912#[derive(Debug, Clone, PartialEq)]
913pub struct ParameterAnnotations {
914 pub parameters: Vec<Vec<Annotation>>,
915}
916
917#[derive(Debug, Clone, PartialEq)]
918pub struct TypeAnnotation {
919 pub target_type: u8,
920 pub target_info: TypeAnnotationTargetInfo,
921 pub target_path: TypePath,
922 pub annotation: Annotation,
923}
924
925#[derive(Debug, Clone, PartialEq)]
926pub struct TypePath {
927 pub path: Vec<TypePathEntry>,
928}
929
930#[derive(Debug, Clone, PartialEq)]
931pub struct TypePathEntry {
932 pub type_path_kind: u8,
933 pub type_argument_index: u8,
934}
935
936#[derive(Debug, Clone, PartialEq)]
937pub enum TypeAnnotationTargetInfo {
938 TypeParameter {
939 type_parameter_index: u8,
940 },
941 Supertype {
942 supertype_index: u16,
943 },
944 TypeParameterBound {
945 type_parameter_index: u8,
946 bound_index: u8,
947 },
948 Empty,
949 FormalParameter {
950 formal_parameter_index: u8,
951 },
952 Throws {
953 throws_type_index: u16,
954 },
955 LocalVar {
956 table: Vec<LocalVarTargetTableEntry>,
957 },
958 Catch {
959 exception_table_index: u16,
960 },
961 Offset {
962 offset: u16,
963 },
964 TypeArgument {
965 offset: u16,
966 type_argument_index: u8,
967 },
968}
969
970#[derive(Debug, Clone, PartialEq)]
971pub struct LocalVarTargetTableEntry {
972 pub start_pc: u16,
973 pub length: u16,
974 pub index: u16,
975}
976
977#[derive(Debug, Clone)]
978pub struct CodeAttribute {
979 pub max_stack: u16,
980 pub max_locals: u16,
981 pub code: Vec<u8>,
982 pub instructions: Vec<Insn>,
983 pub insn_nodes: Vec<AbstractInsnNode>,
984 pub exception_table: Vec<ExceptionTableEntry>,
985 pub try_catch_blocks: Vec<TryCatchBlockNode>,
986 pub attributes: Vec<AttributeInfo>,
987}
988
989#[derive(Debug, Clone)]
990pub struct ExceptionTableEntry {
991 pub start_pc: u16,
992 pub end_pc: u16,
993 pub handler_pc: u16,
994 pub catch_type: u16,
995}
996
997#[derive(Debug, Clone)]
998pub struct LineNumber {
999 pub start_pc: u16,
1000 pub line_number: u16,
1001}
1002
1003#[derive(Debug, Clone)]
1004pub struct LocalVariable {
1005 pub start_pc: u16,
1006 pub length: u16,
1007 pub name_index: u16,
1008 pub descriptor_index: u16,
1009 pub index: u16,
1010}
1011
1012#[derive(Debug, Clone)]
1013pub struct InnerClass {
1014 pub inner_class_info_index: u16,
1015 pub outer_class_info_index: u16,
1016 pub inner_name_index: u16,
1017 pub inner_class_access_flags: u16,
1018}
1019
1020#[derive(Debug, Clone)]
1021pub struct BootstrapMethod {
1022 pub bootstrap_method_ref: u16,
1023 pub bootstrap_arguments: Vec<u16>,
1024}
1025
1026#[derive(Debug, Clone)]
1027pub struct MethodParameter {
1028 pub name_index: u16,
1029 pub access_flags: u16,
1030}
1031
1032#[derive(Debug, Clone, PartialEq, Eq)]
1033pub enum VerificationTypeInfo {
1034 Top,
1035 Integer,
1036 Float,
1037 Long,
1038 Double,
1039 Null,
1040 UninitializedThis,
1041 Object { cpool_index: u16 },
1042 Uninitialized { offset: u16 },
1043}
1044
1045#[derive(Debug, Clone)]
1046pub enum StackMapFrame {
1047 SameFrame {
1048 offset_delta: u16,
1049 },
1050 SameLocals1StackItemFrame {
1051 offset_delta: u16,
1052 stack: VerificationTypeInfo,
1053 },
1054 SameLocals1StackItemFrameExtended {
1055 offset_delta: u16,
1056 stack: VerificationTypeInfo,
1057 },
1058 ChopFrame {
1059 offset_delta: u16,
1060 k: u8,
1061 },
1062 SameFrameExtended {
1063 offset_delta: u16,
1064 },
1065 AppendFrame {
1066 offset_delta: u16,
1067 locals: Vec<VerificationTypeInfo>,
1068 },
1069 FullFrame {
1070 offset_delta: u16,
1071 locals: Vec<VerificationTypeInfo>,
1072 stack: Vec<VerificationTypeInfo>,
1073 },
1074}
1075
1076pub fn read_class_file(bytes: &[u8]) -> Result<ClassFile, ClassReadError> {
1077 let mut reader = ByteReader::new(bytes);
1078 let magic = reader.read_u4()?;
1079 if magic != 0xCAFEBABE {
1080 return Err(ClassReadError::InvalidMagic(magic));
1081 }
1082 let minor_version = reader.read_u2()?;
1083 let major_version = reader.read_u2()?;
1084 if major_version > constants::V25 {
1085 return Err(ClassReadError::InvalidClassVersion(major_version));
1086 }
1087 let constant_pool = read_constant_pool(&mut reader)?;
1088 let access_flags = reader.read_u2()?;
1089 let this_class = reader.read_u2()?;
1090 let super_class = reader.read_u2()?;
1091 let interfaces = read_u2_table(&mut reader)?;
1092 let fields = read_fields(&mut reader, &constant_pool)?;
1093 let methods = read_methods(&mut reader, &constant_pool)?;
1094 let attributes = read_attributes(&mut reader, &constant_pool)?;
1095
1096 Ok(ClassFile {
1097 minor_version,
1098 major_version,
1099 constant_pool,
1100 access_flags,
1101 this_class,
1102 super_class,
1103 interfaces,
1104 fields,
1105 methods,
1106 attributes,
1107 })
1108}
1109
1110fn read_constant_pool(reader: &mut ByteReader<'_>) -> Result<Vec<CpInfo>, ClassReadError> {
1111 let count = reader.read_u2()? as usize;
1112 let mut pool = Vec::with_capacity(count);
1113 pool.push(CpInfo::Unusable);
1114
1115 let mut index = 1;
1116 while index < count {
1117 let tag = reader.read_u1()?;
1118 let entry = match tag {
1119 1 => {
1120 let len = reader.read_u2()? as usize;
1121 let bytes = reader.read_bytes(len)?;
1122 let value = decode_modified_utf8(&bytes)?;
1123 CpInfo::Utf8(value)
1124 }
1125 3 => {
1126 let value = reader.read_u4()? as i32;
1127 CpInfo::Integer(value)
1128 }
1129 4 => {
1130 let value = f32::from_bits(reader.read_u4()?);
1131 CpInfo::Float(value)
1132 }
1133 5 => {
1134 let value = reader.read_u8()? as i64;
1135 CpInfo::Long(value)
1136 }
1137 6 => {
1138 let value = f64::from_bits(reader.read_u8()?);
1139 CpInfo::Double(value)
1140 }
1141 7 => CpInfo::Class {
1142 name_index: reader.read_u2()?,
1143 },
1144 8 => CpInfo::String {
1145 string_index: reader.read_u2()?,
1146 },
1147 9 => CpInfo::Fieldref {
1148 class_index: reader.read_u2()?,
1149 name_and_type_index: reader.read_u2()?,
1150 },
1151 10 => CpInfo::Methodref {
1152 class_index: reader.read_u2()?,
1153 name_and_type_index: reader.read_u2()?,
1154 },
1155 11 => CpInfo::InterfaceMethodref {
1156 class_index: reader.read_u2()?,
1157 name_and_type_index: reader.read_u2()?,
1158 },
1159 12 => CpInfo::NameAndType {
1160 name_index: reader.read_u2()?,
1161 descriptor_index: reader.read_u2()?,
1162 },
1163 15 => CpInfo::MethodHandle {
1164 reference_kind: reader.read_u1()?,
1165 reference_index: reader.read_u2()?,
1166 },
1167 16 => CpInfo::MethodType {
1168 descriptor_index: reader.read_u2()?,
1169 },
1170 17 => CpInfo::Dynamic {
1171 bootstrap_method_attr_index: reader.read_u2()?,
1172 name_and_type_index: reader.read_u2()?,
1173 },
1174 18 => CpInfo::InvokeDynamic {
1175 bootstrap_method_attr_index: reader.read_u2()?,
1176 name_and_type_index: reader.read_u2()?,
1177 },
1178 19 => CpInfo::Module {
1179 name_index: reader.read_u2()?,
1180 },
1181 20 => CpInfo::Package {
1182 name_index: reader.read_u2()?,
1183 },
1184 _ => return Err(ClassReadError::InvalidConstantPoolTag(tag)),
1185 };
1186
1187 pool.push(entry);
1188
1189 if tag == 5 || tag == 6 {
1190 pool.push(CpInfo::Unusable);
1191 index += 2;
1192 } else {
1193 index += 1;
1194 }
1195 }
1196
1197 Ok(pool)
1198}
1199
1200fn read_u2_table(reader: &mut ByteReader<'_>) -> Result<Vec<u16>, ClassReadError> {
1201 let count = reader.read_u2()? as usize;
1202 let mut values = Vec::with_capacity(count);
1203 for _ in 0..count {
1204 values.push(reader.read_u2()?);
1205 }
1206 Ok(values)
1207}
1208
1209fn read_fields(
1210 reader: &mut ByteReader<'_>,
1211 cp: &[CpInfo],
1212) -> Result<Vec<FieldInfo>, ClassReadError> {
1213 let count = reader.read_u2()? as usize;
1214 let mut fields = Vec::with_capacity(count);
1215 for _ in 0..count {
1216 let access_flags = reader.read_u2()?;
1217 let name_index = reader.read_u2()?;
1218 let descriptor_index = reader.read_u2()?;
1219 let attributes = read_attributes(reader, cp)?;
1220 fields.push(FieldInfo {
1221 access_flags,
1222 name_index,
1223 descriptor_index,
1224 attributes,
1225 });
1226 }
1227 Ok(fields)
1228}
1229
1230fn read_methods(
1231 reader: &mut ByteReader<'_>,
1232 cp: &[CpInfo],
1233) -> Result<Vec<MethodInfo>, ClassReadError> {
1234 let count = reader.read_u2()? as usize;
1235 let mut methods = Vec::with_capacity(count);
1236 for _ in 0..count {
1237 let access_flags = reader.read_u2()?;
1238 let name_index = reader.read_u2()?;
1239 let descriptor_index = reader.read_u2()?;
1240 let attributes = read_attributes(reader, cp)?;
1241 methods.push(MethodInfo {
1242 access_flags,
1243 name_index,
1244 descriptor_index,
1245 attributes,
1246 });
1247 }
1248 Ok(methods)
1249}
1250
1251fn read_attributes(
1252 reader: &mut ByteReader<'_>,
1253 cp: &[CpInfo],
1254) -> Result<Vec<AttributeInfo>, ClassReadError> {
1255 let count = reader.read_u2()? as usize;
1256 let mut attributes = Vec::with_capacity(count);
1257 for _ in 0..count {
1258 let name_index = reader.read_u2()?;
1259 let length = reader.read_u4()? as usize;
1260 let name = cp_utf8(cp, name_index)?;
1261 let info = reader.read_bytes(length)?;
1262 let attribute = parse_attribute(name, info, cp)?;
1263 attributes.push(attribute);
1264 }
1265 Ok(attributes)
1266}
1267
1268fn parse_attribute(
1269 name: &str,
1270 info: Vec<u8>,
1271 cp: &[CpInfo],
1272) -> Result<AttributeInfo, ClassReadError> {
1273 let mut reader = ByteReader::new(&info);
1274 let attribute = match name {
1275 "Code" => {
1276 let max_stack = reader.read_u2()?;
1277 let max_locals = reader.read_u2()?;
1278 let code_length = reader.read_u4()? as usize;
1279 let code = reader.read_bytes(code_length)?;
1280 let instructions = parse_code_instructions(&code)?;
1281 let exception_table_length = reader.read_u2()? as usize;
1282 let mut exception_table = Vec::with_capacity(exception_table_length);
1283 for _ in 0..exception_table_length {
1284 exception_table.push(ExceptionTableEntry {
1285 start_pc: reader.read_u2()?,
1286 end_pc: reader.read_u2()?,
1287 handler_pc: reader.read_u2()?,
1288 catch_type: reader.read_u2()?,
1289 });
1290 }
1291 let attributes = read_attributes(&mut reader, cp)?;
1292 let (mut insn_nodes, try_catch_blocks, label_by_offset) =
1293 build_insn_nodes(&code, &exception_table, cp)?;
1294 let line_numbers = attributes.iter().find_map(|attr| match attr {
1295 AttributeInfo::LineNumberTable { entries } => Some(entries.as_slice()),
1296 _ => None,
1297 });
1298 if let Some(entries) = line_numbers {
1299 insn_nodes = attach_line_numbers(insn_nodes, entries, &label_by_offset);
1300 }
1301 AttributeInfo::Code(CodeAttribute {
1302 max_stack,
1303 max_locals,
1304 code,
1305 instructions,
1306 insn_nodes,
1307 exception_table,
1308 try_catch_blocks,
1309 attributes,
1310 })
1311 }
1312 "ConstantValue" => AttributeInfo::ConstantValue {
1313 constantvalue_index: reader.read_u2()?,
1314 },
1315 "Exceptions" => {
1316 let count = reader.read_u2()? as usize;
1317 let mut exception_index_table = Vec::with_capacity(count);
1318 for _ in 0..count {
1319 exception_index_table.push(reader.read_u2()?);
1320 }
1321 AttributeInfo::Exceptions {
1322 exception_index_table,
1323 }
1324 }
1325 "SourceFile" => AttributeInfo::SourceFile {
1326 sourcefile_index: reader.read_u2()?,
1327 },
1328 "LineNumberTable" => {
1329 let count = reader.read_u2()? as usize;
1330 let mut entries = Vec::with_capacity(count);
1331 for _ in 0..count {
1332 entries.push(LineNumber {
1333 start_pc: reader.read_u2()?,
1334 line_number: reader.read_u2()?,
1335 });
1336 }
1337 AttributeInfo::LineNumberTable { entries }
1338 }
1339 "LocalVariableTable" => {
1340 let count = reader.read_u2()? as usize;
1341 let mut entries = Vec::with_capacity(count);
1342 for _ in 0..count {
1343 entries.push(LocalVariable {
1344 start_pc: reader.read_u2()?,
1345 length: reader.read_u2()?,
1346 name_index: reader.read_u2()?,
1347 descriptor_index: reader.read_u2()?,
1348 index: reader.read_u2()?,
1349 });
1350 }
1351 AttributeInfo::LocalVariableTable { entries }
1352 }
1353 "Signature" => AttributeInfo::Signature {
1354 signature_index: reader.read_u2()?,
1355 },
1356 "StackMapTable" => {
1357 let count = reader.read_u2()? as usize;
1358 let mut entries = Vec::with_capacity(count);
1359 for _ in 0..count {
1360 let frame_type = reader.read_u1()?;
1361 let frame = match frame_type {
1362 0..=63 => StackMapFrame::SameFrame {
1363 offset_delta: frame_type as u16,
1364 },
1365 64..=127 => StackMapFrame::SameLocals1StackItemFrame {
1366 offset_delta: (frame_type - 64) as u16,
1367 stack: parse_verification_type(&mut reader)?,
1368 },
1369 247 => StackMapFrame::SameLocals1StackItemFrameExtended {
1370 offset_delta: reader.read_u2()?,
1371 stack: parse_verification_type(&mut reader)?,
1372 },
1373 248..=250 => StackMapFrame::ChopFrame {
1374 offset_delta: reader.read_u2()?,
1375 k: 251 - frame_type,
1376 },
1377 251 => StackMapFrame::SameFrameExtended {
1378 offset_delta: reader.read_u2()?,
1379 },
1380 252..=254 => {
1381 let offset_delta = reader.read_u2()?;
1382 let locals_count = (frame_type - 251) as usize;
1383 let mut locals = Vec::with_capacity(locals_count);
1384 for _ in 0..locals_count {
1385 locals.push(parse_verification_type(&mut reader)?);
1386 }
1387 StackMapFrame::AppendFrame {
1388 offset_delta,
1389 locals,
1390 }
1391 }
1392 255 => {
1393 let offset_delta = reader.read_u2()?;
1394 let locals_count = reader.read_u2()? as usize;
1395 let mut locals = Vec::with_capacity(locals_count);
1396 for _ in 0..locals_count {
1397 locals.push(parse_verification_type(&mut reader)?);
1398 }
1399 let stack_count = reader.read_u2()? as usize;
1400 let mut stack = Vec::with_capacity(stack_count);
1401 for _ in 0..stack_count {
1402 stack.push(parse_verification_type(&mut reader)?);
1403 }
1404 StackMapFrame::FullFrame {
1405 offset_delta,
1406 locals,
1407 stack,
1408 }
1409 }
1410 _ => {
1411 return Err(ClassReadError::InvalidAttribute(
1412 "StackMapTable".to_string(),
1413 ));
1414 }
1415 };
1416 entries.push(frame);
1417 }
1418 AttributeInfo::StackMapTable { entries }
1419 }
1420 "Deprecated" => AttributeInfo::Deprecated,
1421 "Synthetic" => AttributeInfo::Synthetic,
1422 "InnerClasses" => {
1423 let count = reader.read_u2()? as usize;
1424 let mut classes = Vec::with_capacity(count);
1425 for _ in 0..count {
1426 classes.push(InnerClass {
1427 inner_class_info_index: reader.read_u2()?,
1428 outer_class_info_index: reader.read_u2()?,
1429 inner_name_index: reader.read_u2()?,
1430 inner_class_access_flags: reader.read_u2()?,
1431 });
1432 }
1433 AttributeInfo::InnerClasses { classes }
1434 }
1435 "EnclosingMethod" => AttributeInfo::EnclosingMethod {
1436 class_index: reader.read_u2()?,
1437 method_index: reader.read_u2()?,
1438 },
1439 "Module" => AttributeInfo::Module(parse_module_attribute(&mut reader)?),
1440 "ModulePackages" => {
1441 let count = reader.read_u2()? as usize;
1442 let mut package_index_table = Vec::with_capacity(count);
1443 for _ in 0..count {
1444 package_index_table.push(reader.read_u2()?);
1445 }
1446 AttributeInfo::ModulePackages {
1447 package_index_table,
1448 }
1449 }
1450 "ModuleMainClass" => AttributeInfo::ModuleMainClass {
1451 main_class_index: reader.read_u2()?,
1452 },
1453 "BootstrapMethods" => {
1454 let count = reader.read_u2()? as usize;
1455 let mut methods = Vec::with_capacity(count);
1456 for _ in 0..count {
1457 let bootstrap_method_ref = reader.read_u2()?;
1458 let arg_count = reader.read_u2()? as usize;
1459 let mut bootstrap_arguments = Vec::with_capacity(arg_count);
1460 for _ in 0..arg_count {
1461 bootstrap_arguments.push(reader.read_u2()?);
1462 }
1463 methods.push(BootstrapMethod {
1464 bootstrap_method_ref,
1465 bootstrap_arguments,
1466 });
1467 }
1468 AttributeInfo::BootstrapMethods { methods }
1469 }
1470 "MethodParameters" => {
1471 let count = reader.read_u1()? as usize;
1472 let mut parameters = Vec::with_capacity(count);
1473 for _ in 0..count {
1474 parameters.push(MethodParameter {
1475 name_index: reader.read_u2()?,
1476 access_flags: reader.read_u2()?,
1477 });
1478 }
1479 AttributeInfo::MethodParameters { parameters }
1480 }
1481 "RuntimeVisibleAnnotations" => {
1482 let annotations = parse_annotations(&mut reader)?;
1483 AttributeInfo::RuntimeVisibleAnnotations { annotations }
1484 }
1485 "RuntimeInvisibleAnnotations" => {
1486 let annotations = parse_annotations(&mut reader)?;
1487 AttributeInfo::RuntimeInvisibleAnnotations { annotations }
1488 }
1489 "RuntimeVisibleParameterAnnotations" => {
1490 let parameters = parse_parameter_annotations(&mut reader)?;
1491 AttributeInfo::RuntimeVisibleParameterAnnotations { parameters }
1492 }
1493 "RuntimeInvisibleParameterAnnotations" => {
1494 let parameters = parse_parameter_annotations(&mut reader)?;
1495 AttributeInfo::RuntimeInvisibleParameterAnnotations { parameters }
1496 }
1497 "RuntimeVisibleTypeAnnotations" => {
1498 let annotations = parse_type_annotations(&mut reader)?;
1499 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations }
1500 }
1501 "RuntimeInvisibleTypeAnnotations" => {
1502 let annotations = parse_type_annotations(&mut reader)?;
1503 AttributeInfo::RuntimeInvisibleTypeAnnotations { annotations }
1504 }
1505 _ => {
1506 return Ok(AttributeInfo::Unknown {
1507 name: name.to_string(),
1508 info,
1509 });
1510 }
1511 };
1512
1513 if reader.remaining() != 0 {
1514 return Err(ClassReadError::InvalidAttribute(name.to_string()));
1515 }
1516
1517 Ok(attribute)
1518}
1519
1520fn parse_module_attribute(reader: &mut ByteReader<'_>) -> Result<ModuleAttribute, ClassReadError> {
1521 let module_name_index = reader.read_u2()?;
1522 let module_flags = reader.read_u2()?;
1523 let module_version_index = reader.read_u2()?;
1524
1525 let requires_count = reader.read_u2()? as usize;
1526 let mut requires = Vec::with_capacity(requires_count);
1527 for _ in 0..requires_count {
1528 requires.push(ModuleRequire {
1529 requires_index: reader.read_u2()?,
1530 requires_flags: reader.read_u2()?,
1531 requires_version_index: reader.read_u2()?,
1532 });
1533 }
1534
1535 let exports_count = reader.read_u2()? as usize;
1536 let mut exports = Vec::with_capacity(exports_count);
1537 for _ in 0..exports_count {
1538 let exports_index = reader.read_u2()?;
1539 let exports_flags = reader.read_u2()?;
1540 let exports_to_count = reader.read_u2()? as usize;
1541 let mut exports_to_index = Vec::with_capacity(exports_to_count);
1542 for _ in 0..exports_to_count {
1543 exports_to_index.push(reader.read_u2()?);
1544 }
1545 exports.push(ModuleExport {
1546 exports_index,
1547 exports_flags,
1548 exports_to_index,
1549 });
1550 }
1551
1552 let opens_count = reader.read_u2()? as usize;
1553 let mut opens = Vec::with_capacity(opens_count);
1554 for _ in 0..opens_count {
1555 let opens_index = reader.read_u2()?;
1556 let opens_flags = reader.read_u2()?;
1557 let opens_to_count = reader.read_u2()? as usize;
1558 let mut opens_to_index = Vec::with_capacity(opens_to_count);
1559 for _ in 0..opens_to_count {
1560 opens_to_index.push(reader.read_u2()?);
1561 }
1562 opens.push(ModuleOpen {
1563 opens_index,
1564 opens_flags,
1565 opens_to_index,
1566 });
1567 }
1568
1569 let uses_count = reader.read_u2()? as usize;
1570 let mut uses_index = Vec::with_capacity(uses_count);
1571 for _ in 0..uses_count {
1572 uses_index.push(reader.read_u2()?);
1573 }
1574
1575 let provides_count = reader.read_u2()? as usize;
1576 let mut provides = Vec::with_capacity(provides_count);
1577 for _ in 0..provides_count {
1578 let provides_index = reader.read_u2()?;
1579 let provides_with_count = reader.read_u2()? as usize;
1580 let mut provides_with_index = Vec::with_capacity(provides_with_count);
1581 for _ in 0..provides_with_count {
1582 provides_with_index.push(reader.read_u2()?);
1583 }
1584 provides.push(ModuleProvide {
1585 provides_index,
1586 provides_with_index,
1587 });
1588 }
1589
1590 Ok(ModuleAttribute {
1591 module_name_index,
1592 module_flags,
1593 module_version_index,
1594 requires,
1595 exports,
1596 opens,
1597 uses_index,
1598 provides,
1599 })
1600}
1601
1602fn parse_annotations(reader: &mut ByteReader) -> Result<Vec<Annotation>, ClassReadError> {
1603 let num = reader.read_u2()? as usize;
1604 let mut out = Vec::with_capacity(num);
1605 for _ in 0..num {
1606 out.push(parse_annotation(reader)?);
1607 }
1608 Ok(out)
1609}
1610
1611fn parse_annotation(reader: &mut ByteReader) -> Result<Annotation, ClassReadError> {
1612 let type_descriptor_index = reader.read_u2()?;
1613 let num_pairs = reader.read_u2()? as usize;
1614 let mut element_value_pairs = Vec::with_capacity(num_pairs);
1615 for _ in 0..num_pairs {
1616 let element_name_index = reader.read_u2()?;
1617 let value = parse_element_value(reader)?;
1618 element_value_pairs.push(ElementValuePair {
1619 element_name_index,
1620 value,
1621 });
1622 }
1623 Ok(Annotation {
1624 type_descriptor_index,
1625 element_value_pairs,
1626 })
1627}
1628
1629fn parse_parameter_annotations(
1630 reader: &mut ByteReader,
1631) -> Result<ParameterAnnotations, ClassReadError> {
1632 let num_params = reader.read_u1()? as usize;
1633 let mut parameters = Vec::with_capacity(num_params);
1634 for _ in 0..num_params {
1635 let num_ann = reader.read_u2()? as usize;
1636 let mut anns = Vec::with_capacity(num_ann);
1637 for _ in 0..num_ann {
1638 anns.push(parse_annotation(reader)?);
1639 }
1640 parameters.push(anns);
1641 }
1642 Ok(ParameterAnnotations { parameters })
1643}
1644
1645fn parse_type_annotations(reader: &mut ByteReader) -> Result<Vec<TypeAnnotation>, ClassReadError> {
1646 let num = reader.read_u2()? as usize;
1647 let mut out = Vec::with_capacity(num);
1648 for _ in 0..num {
1649 out.push(parse_type_annotation(reader)?);
1650 }
1651 Ok(out)
1652}
1653
1654fn parse_type_annotation(reader: &mut ByteReader) -> Result<TypeAnnotation, ClassReadError> {
1655 let target_type = reader.read_u1()?;
1656 let target_info = parse_type_annotation_target_info(reader, target_type)?;
1657 let target_path = parse_type_path(reader)?;
1658 let annotation = parse_annotation(reader)?;
1659 Ok(TypeAnnotation {
1660 target_type,
1661 target_info,
1662 target_path,
1663 annotation,
1664 })
1665}
1666
1667fn parse_type_path(reader: &mut ByteReader) -> Result<TypePath, ClassReadError> {
1668 let path_length = reader.read_u1()? as usize;
1669 let mut path = Vec::with_capacity(path_length);
1670 for _ in 0..path_length {
1671 path.push(TypePathEntry {
1672 type_path_kind: reader.read_u1()?,
1673 type_argument_index: reader.read_u1()?,
1674 });
1675 }
1676 Ok(TypePath { path })
1677}
1678
1679fn parse_type_annotation_target_info(
1680 reader: &mut ByteReader,
1681 target_type: u8,
1682) -> Result<TypeAnnotationTargetInfo, ClassReadError> {
1683 use crate::constants::*;
1684
1685 let ti = match target_type {
1686 TA_TARGET_CLASS_TYPE_PARAMETER | TA_TARGET_METHOD_TYPE_PARAMETER => {
1687 TypeAnnotationTargetInfo::TypeParameter {
1688 type_parameter_index: reader.read_u1()?,
1689 }
1690 }
1691
1692 TA_TARGET_CLASS_EXTENDS => TypeAnnotationTargetInfo::Supertype {
1693 supertype_index: reader.read_u2()?,
1694 },
1695
1696 TA_TARGET_CLASS_TYPE_PARAMETER_BOUND | TA_TARGET_METHOD_TYPE_PARAMETER_BOUND => {
1697 TypeAnnotationTargetInfo::TypeParameterBound {
1698 type_parameter_index: reader.read_u1()?,
1699 bound_index: reader.read_u1()?,
1700 }
1701 }
1702
1703 TA_TARGET_FIELD | TA_TARGET_METHOD_RETURN | TA_TARGET_METHOD_RECEIVER => {
1704 TypeAnnotationTargetInfo::Empty
1705 }
1706
1707 TA_TARGET_METHOD_FORMAL_PARAMETER => TypeAnnotationTargetInfo::FormalParameter {
1708 formal_parameter_index: reader.read_u1()?,
1709 },
1710
1711 TA_TARGET_THROWS => TypeAnnotationTargetInfo::Throws {
1712 throws_type_index: reader.read_u2()?,
1713 },
1714
1715 TA_TARGET_LOCAL_VARIABLE | TA_TARGET_RESOURCE_VARIABLE => {
1716 let table_length = reader.read_u2()? as usize;
1717 let mut table = Vec::with_capacity(table_length);
1718 for _ in 0..table_length {
1719 table.push(LocalVarTargetTableEntry {
1720 start_pc: reader.read_u2()?,
1721 length: reader.read_u2()?,
1722 index: reader.read_u2()?,
1723 });
1724 }
1725 TypeAnnotationTargetInfo::LocalVar { table }
1726 }
1727
1728 TA_TARGET_EXCEPTION_PARAMETER => TypeAnnotationTargetInfo::Catch {
1729 exception_table_index: reader.read_u2()?,
1730 },
1731
1732 TA_TARGET_INSTANCEOF
1733 | TA_TARGET_NEW
1734 | TA_TARGET_CONSTRUCTOR_REFERENCE_RECEIVER
1735 | TA_TARGET_METHOD_REFERENCE_RECEIVER => TypeAnnotationTargetInfo::Offset {
1736 offset: reader.read_u2()?,
1737 },
1738
1739 TA_TARGET_CAST
1740 | TA_TARGET_CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1741 | TA_TARGET_METHOD_INVOCATION_TYPE_ARGUMENT
1742 | TA_TARGET_CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1743 | TA_TARGET_METHOD_REFERENCE_TYPE_ARGUMENT => TypeAnnotationTargetInfo::TypeArgument {
1744 offset: reader.read_u2()?,
1745 type_argument_index: reader.read_u1()?,
1746 },
1747
1748 _ => {
1749 return Err(ClassReadError::InvalidAttribute(format!(
1750 "TypeAnnotationTargetInfo(target_type=0x{:02X})",
1751 target_type
1752 )));
1753 }
1754 };
1755
1756 Ok(ti)
1757}
1758
1759fn parse_element_value(reader: &mut ByteReader) -> Result<ElementValue, ClassReadError> {
1760 let tag = reader.read_u1()?;
1761 let v = match tag {
1762 b'B' | b'C' | b'D' | b'F' | b'I' | b'J' | b'S' | b'Z' | b's' => {
1763 ElementValue::ConstValueIndex {
1764 tag,
1765 const_value_index: reader.read_u2()?,
1766 }
1767 }
1768 b'e' => ElementValue::EnumConstValue {
1769 type_name_index: reader.read_u2()?,
1770 const_name_index: reader.read_u2()?,
1771 },
1772 b'c' => ElementValue::ClassInfoIndex {
1773 class_info_index: reader.read_u2()?,
1774 },
1775 b'@' => ElementValue::AnnotationValue(Box::new(parse_annotation(reader)?)),
1776 b'[' => {
1777 let n = reader.read_u2()? as usize;
1778 let mut items = Vec::with_capacity(n);
1779 for _ in 0..n {
1780 items.push(parse_element_value(reader)?);
1781 }
1782 ElementValue::ArrayValue(items)
1783 }
1784 _ => {
1785 return Err(ClassReadError::InvalidAttribute(
1786 "AnnotationElementValue".to_string(),
1787 ));
1788 }
1789 };
1790 Ok(v)
1791}
1792
1793fn parse_verification_type(
1794 reader: &mut ByteReader<'_>,
1795) -> Result<VerificationTypeInfo, ClassReadError> {
1796 let tag = reader.read_u1()?;
1797 let kind = match tag {
1798 0 => VerificationTypeInfo::Top,
1799 1 => VerificationTypeInfo::Integer,
1800 2 => VerificationTypeInfo::Float,
1801 3 => VerificationTypeInfo::Double,
1802 4 => VerificationTypeInfo::Long,
1803 5 => VerificationTypeInfo::Null,
1804 6 => VerificationTypeInfo::UninitializedThis,
1805 7 => VerificationTypeInfo::Object {
1806 cpool_index: reader.read_u2()?,
1807 },
1808 8 => VerificationTypeInfo::Uninitialized {
1809 offset: reader.read_u2()?,
1810 },
1811 _ => {
1812 return Err(ClassReadError::InvalidAttribute(
1813 "StackMapTable".to_string(),
1814 ));
1815 }
1816 };
1817 Ok(kind)
1818}
1819
1820fn cp_utf8(cp: &[CpInfo], index: u16) -> Result<&str, ClassReadError> {
1821 match cp.get(index as usize) {
1822 Some(CpInfo::Utf8(value)) => Ok(value.as_str()),
1823 _ => Err(ClassReadError::InvalidIndex(index)),
1824 }
1825}
1826
1827fn cp_class_name(cp: &[CpInfo], index: u16) -> Result<&str, ClassReadError> {
1828 match cp.get(index as usize) {
1829 Some(CpInfo::Class { name_index }) => cp_utf8(cp, *name_index),
1830 _ => Err(ClassReadError::InvalidIndex(index)),
1831 }
1832}
1833
1834fn cp_name_and_type(cp: &[CpInfo], index: u16) -> Result<(&str, &str), ClassReadError> {
1835 match cp.get(index as usize) {
1836 Some(CpInfo::NameAndType {
1837 name_index,
1838 descriptor_index,
1839 }) => Ok((cp_utf8(cp, *name_index)?, cp_utf8(cp, *descriptor_index)?)),
1840 _ => Err(ClassReadError::InvalidIndex(index)),
1841 }
1842}
1843
1844fn cp_field_ref(cp: &[CpInfo], index: u16) -> Result<(&str, &str, &str), ClassReadError> {
1845 match cp.get(index as usize) {
1846 Some(CpInfo::Fieldref {
1847 class_index,
1848 name_and_type_index,
1849 }) => {
1850 let owner = cp_class_name(cp, *class_index)?;
1851 let (name, desc) = cp_name_and_type(cp, *name_and_type_index)?;
1852 Ok((owner, name, desc))
1853 }
1854 _ => Err(ClassReadError::InvalidIndex(index)),
1855 }
1856}
1857
1858fn cp_method_ref(cp: &[CpInfo], index: u16) -> Result<(&str, &str, &str, bool), ClassReadError> {
1859 match cp.get(index as usize) {
1860 Some(CpInfo::Methodref {
1861 class_index,
1862 name_and_type_index,
1863 }) => {
1864 let owner = cp_class_name(cp, *class_index)?;
1865 let (name, desc) = cp_name_and_type(cp, *name_and_type_index)?;
1866 Ok((owner, name, desc, false))
1867 }
1868 Some(CpInfo::InterfaceMethodref {
1869 class_index,
1870 name_and_type_index,
1871 }) => {
1872 let owner = cp_class_name(cp, *class_index)?;
1873 let (name, desc) = cp_name_and_type(cp, *name_and_type_index)?;
1874 Ok((owner, name, desc, true))
1875 }
1876 _ => Err(ClassReadError::InvalidIndex(index)),
1877 }
1878}
1879
1880fn cp_invoke_dynamic(cp: &[CpInfo], index: u16) -> Result<(&str, &str), ClassReadError> {
1881 match cp.get(index as usize) {
1882 Some(CpInfo::InvokeDynamic {
1883 name_and_type_index,
1884 ..
1885 }) => cp_name_and_type(cp, *name_and_type_index),
1886 _ => Err(ClassReadError::InvalidIndex(index)),
1887 }
1888}
1889
1890fn cp_ldc_constant(cp: &[CpInfo], index: u16) -> Result<LdcConstant, ClassReadError> {
1891 match cp.get(index as usize) {
1892 Some(CpInfo::Integer(value)) => Ok(LdcConstant::Integer(*value)),
1893 Some(CpInfo::Float(value)) => Ok(LdcConstant::Float(*value)),
1894 Some(CpInfo::Long(value)) => Ok(LdcConstant::Long(*value)),
1895 Some(CpInfo::Double(value)) => Ok(LdcConstant::Double(*value)),
1896 Some(CpInfo::String { string_index }) => {
1897 Ok(LdcConstant::String(cp_utf8(cp, *string_index)?.to_string()))
1898 }
1899 Some(CpInfo::Class { name_index }) => {
1900 Ok(LdcConstant::Class(cp_utf8(cp, *name_index)?.to_string()))
1901 }
1902 Some(CpInfo::MethodType { descriptor_index }) => Ok(LdcConstant::MethodType(
1903 cp_utf8(cp, *descriptor_index)?.to_string(),
1904 )),
1905 Some(CpInfo::MethodHandle {
1906 reference_kind,
1907 reference_index,
1908 }) => Ok(LdcConstant::MethodHandle {
1909 reference_kind: *reference_kind,
1910 reference_index: *reference_index,
1911 }),
1912 Some(CpInfo::Dynamic { .. }) => Ok(LdcConstant::Dynamic),
1913 _ => Err(ClassReadError::InvalidIndex(index)),
1914 }
1915}
1916
1917fn decode_modified_utf8(bytes: &[u8]) -> Result<String, ClassReadError> {
1918 let mut code_units = Vec::with_capacity(bytes.len());
1919 let mut i = 0;
1920 while i < bytes.len() {
1921 let byte = bytes[i];
1922 if byte & 0x80 == 0 {
1923 code_units.push(byte as u16);
1924 i += 1;
1925 } else if byte & 0xE0 == 0xC0 {
1926 if i + 1 >= bytes.len() {
1927 return Err(ClassReadError::Utf8Error("truncated 2-byte".to_string()));
1928 }
1929 let byte2 = bytes[i + 1];
1930 if byte2 & 0xC0 != 0x80 {
1931 return Err(ClassReadError::Utf8Error("invalid 2-byte".to_string()));
1932 }
1933 let value = (((byte & 0x1F) as u16) << 6) | ((byte2 & 0x3F) as u16);
1934 code_units.push(value);
1935 i += 2;
1936 } else if byte & 0xF0 == 0xE0 {
1937 if i + 2 >= bytes.len() {
1938 return Err(ClassReadError::Utf8Error("truncated 3-byte".to_string()));
1939 }
1940 let byte2 = bytes[i + 1];
1941 let byte3 = bytes[i + 2];
1942 if byte2 & 0xC0 != 0x80 || byte3 & 0xC0 != 0x80 {
1943 return Err(ClassReadError::Utf8Error("invalid 3-byte".to_string()));
1944 }
1945 let value = (((byte & 0x0F) as u16) << 12)
1946 | (((byte2 & 0x3F) as u16) << 6)
1947 | ((byte3 & 0x3F) as u16);
1948 code_units.push(value);
1949 i += 3;
1950 } else {
1951 return Err(ClassReadError::Utf8Error(
1952 "invalid leading byte".to_string(),
1953 ));
1954 }
1955 }
1956
1957 String::from_utf16(&code_units)
1958 .map_err(|_| ClassReadError::Utf8Error("invalid utf16".to_string()))
1959}
1960
1961fn parse_code_instructions(code: &[u8]) -> Result<Vec<Insn>, ClassReadError> {
1962 let mut reader = ByteReader::new(code);
1963 let mut insns = Vec::new();
1964
1965 while reader.remaining() > 0 {
1966 let opcode_offset = reader.pos();
1967 let opcode = reader.read_u1()?;
1968 let insn = match opcode {
1969 opcodes::NOP..=opcodes::DCONST_1 => Insn::Simple(opcode.into()),
1970 opcodes::BIPUSH => Insn::Int(IntInsnNode {
1971 insn: opcode.into(),
1972 operand: reader.read_i1()? as i32,
1973 }),
1974 opcodes::SIPUSH => Insn::Int(IntInsnNode {
1975 insn: opcode.into(),
1976 operand: reader.read_i2()? as i32,
1977 }),
1978 opcodes::LDC => Insn::Ldc(LdcInsnNode {
1979 insn: opcode.into(),
1980 value: LdcValue::Index(reader.read_u1()? as u16),
1981 }),
1982 opcodes::LDC_W | opcodes::LDC2_W => Insn::Ldc(LdcInsnNode {
1983 insn: opcode.into(),
1984 value: LdcValue::Index(reader.read_u2()?),
1985 }),
1986 opcodes::ILOAD..=opcodes::ALOAD => Insn::Var(VarInsnNode {
1987 insn: opcode.into(),
1988 var_index: reader.read_u1()? as u16,
1989 }),
1990 opcodes::ILOAD_0..=opcodes::SALOAD => Insn::Simple(opcode.into()),
1991 opcodes::ISTORE..=opcodes::ASTORE => Insn::Var(VarInsnNode {
1992 insn: opcode.into(),
1993 var_index: reader.read_u1()? as u16,
1994 }),
1995 opcodes::ISTORE_0..=opcodes::SASTORE => Insn::Simple(opcode.into()),
1996 opcodes::POP..=opcodes::LXOR => Insn::Simple(opcode.into()),
1997 opcodes::IINC => Insn::Iinc(IincInsnNode {
1998 insn: opcode.into(),
1999 var_index: reader.read_u1()? as u16,
2000 increment: reader.read_i1()? as i16,
2001 }),
2002 opcodes::I2L..=opcodes::DCMPG => Insn::Simple(opcode.into()),
2003 opcodes::IFEQ..=opcodes::JSR => Insn::Jump(JumpInsnNode {
2004 insn: opcode.into(),
2005 offset: reader.read_i2()? as i32,
2006 }),
2007 opcodes::RET => Insn::Var(VarInsnNode {
2008 insn: opcode.into(),
2009 var_index: reader.read_u1()? as u16,
2010 }),
2011 opcodes::TABLESWITCH => read_table_switch(&mut reader, opcode_offset)?,
2012 opcodes::LOOKUPSWITCH => read_lookup_switch(&mut reader, opcode_offset)?,
2013 opcodes::IRETURN..=opcodes::RETURN => Insn::Simple(InsnNode { opcode }),
2014 opcodes::GETSTATIC..=opcodes::PUTFIELD => Insn::Field(FieldInsnNode {
2015 insn: opcode.into(),
2016 field_ref: MemberRef::Index(reader.read_u2()?),
2017 }),
2018 opcodes::INVOKEVIRTUAL..=opcodes::INVOKESTATIC => Insn::Method(MethodInsnNode {
2019 insn: opcode.into(),
2020 method_ref: MemberRef::Index(reader.read_u2()?),
2021 }),
2022 opcodes::INVOKEINTERFACE => {
2023 let method_index = reader.read_u2()?;
2024 let count = reader.read_u1()?;
2025 let _ = reader.read_u1()?;
2026 Insn::InvokeInterface(InvokeInterfaceInsnNode {
2027 insn: opcode.into(),
2028 method_index,
2029 count,
2030 })
2031 }
2032 opcodes::INVOKEDYNAMIC => {
2033 let method_index = reader.read_u2()?;
2034 let _ = reader.read_u2()?;
2035 Insn::InvokeDynamic(InvokeDynamicInsnNode::from_index(method_index))
2036 }
2037 opcodes::NEW => Insn::Type(TypeInsnNode {
2038 insn: opcode.into(),
2039 type_index: reader.read_u2()?,
2040 }),
2041 opcodes::NEWARRAY => Insn::Int(IntInsnNode {
2042 insn: opcode.into(),
2043 operand: reader.read_u1()? as i32,
2044 }),
2045 opcodes::ANEWARRAY => Insn::Type(TypeInsnNode {
2046 insn: opcode.into(),
2047 type_index: reader.read_u2()?,
2048 }),
2049 opcodes::ARRAYLENGTH | opcodes::ATHROW => Insn::Simple(opcode.into()),
2050 opcodes::CHECKCAST | opcodes::INSTANCEOF => Insn::Type(TypeInsnNode {
2051 insn: opcode.into(),
2052 type_index: reader.read_u2()?,
2053 }),
2054 opcodes::MONITORENTER | opcodes::MONITOREXIT => Insn::Simple(opcode.into()),
2055 opcodes::WIDE => read_wide(&mut reader)?,
2056 opcodes::MULTIANEWARRAY => Insn::MultiANewArray(MultiANewArrayInsnNode {
2057 insn: opcode.into(),
2058 type_index: reader.read_u2()?,
2059 dimensions: reader.read_u1()?,
2060 }),
2061 opcodes::IFNULL | opcodes::IFNONNULL => Insn::Jump(JumpInsnNode {
2062 insn: opcode.into(),
2063 offset: reader.read_i2()? as i32,
2064 }),
2065 opcodes::GOTO_W | opcodes::JSR_W => Insn::Jump(JumpInsnNode {
2066 insn: opcode.into(),
2067 offset: reader.read_i4()?,
2068 }),
2069 opcodes::BREAKPOINT => Insn::Simple(opcode.into()),
2070 opcodes::IMPDEP1 | opcodes::IMPDEP2 => Insn::Simple(opcode.into()),
2071 _ => {
2072 return Err(ClassReadError::InvalidOpcode {
2073 opcode,
2074 offset: opcode_offset,
2075 });
2076 }
2077 };
2078
2079 insns.push(insn);
2080 }
2081
2082 Ok(insns)
2083}
2084
2085pub(crate) fn parse_code_instructions_public(code: &[u8]) -> Result<Vec<Insn>, ClassReadError> {
2086 parse_code_instructions(code)
2087}
2088
2089#[derive(Debug, Clone)]
2090struct ParsedInstruction {
2091 offset: u16,
2092 insn: Insn,
2093}
2094
2095fn parse_code_instructions_with_offsets(
2096 code: &[u8],
2097) -> Result<Vec<ParsedInstruction>, ClassReadError> {
2098 let mut reader = ByteReader::new(code);
2099 let mut insns = Vec::new();
2100
2101 while reader.remaining() > 0 {
2102 let opcode_offset = reader.pos();
2103 let opcode = reader.read_u1()?;
2104 let insn = match opcode {
2105 opcodes::NOP..=opcodes::DCONST_1 => Insn::Simple(opcode.into()),
2106 opcodes::BIPUSH => Insn::Int(IntInsnNode {
2107 insn: opcode.into(),
2108 operand: reader.read_i1()? as i32,
2109 }),
2110 opcodes::SIPUSH => Insn::Int(IntInsnNode {
2111 insn: opcode.into(),
2112 operand: reader.read_i2()? as i32,
2113 }),
2114 opcodes::LDC => Insn::Ldc(LdcInsnNode {
2115 insn: opcode.into(),
2116 value: LdcValue::Index(reader.read_u1()? as u16),
2117 }),
2118 opcodes::LDC_W | opcodes::LDC2_W => Insn::Ldc(LdcInsnNode {
2119 insn: opcode.into(),
2120 value: LdcValue::Index(reader.read_u2()?),
2121 }),
2122 opcodes::ILOAD..=opcodes::ALOAD => Insn::Var(VarInsnNode {
2123 insn: opcode.into(),
2124 var_index: reader.read_u1()? as u16,
2125 }),
2126 opcodes::ILOAD_0..=opcodes::SALOAD => Insn::Simple(opcode.into()),
2127 opcodes::ISTORE..=opcodes::ASTORE => Insn::Var(VarInsnNode {
2128 insn: opcode.into(),
2129 var_index: reader.read_u1()? as u16,
2130 }),
2131 opcodes::ISTORE_0..=opcodes::SASTORE => Insn::Simple(opcode.into()),
2132 opcodes::POP..=opcodes::LXOR => Insn::Simple(opcode.into()),
2133 opcodes::IINC => Insn::Iinc(IincInsnNode {
2134 insn: opcode.into(),
2135 var_index: reader.read_u1()? as u16,
2136 increment: reader.read_i1()? as i16,
2137 }),
2138 opcodes::I2L..=opcodes::DCMPG => Insn::Simple(opcode.into()),
2139 opcodes::IFEQ..=opcodes::JSR => Insn::Jump(JumpInsnNode {
2140 insn: opcode.into(),
2141 offset: reader.read_i2()? as i32,
2142 }),
2143 opcodes::RET => Insn::Var(VarInsnNode {
2144 insn: opcode.into(),
2145 var_index: reader.read_u1()? as u16,
2146 }),
2147 opcodes::TABLESWITCH => read_table_switch(&mut reader, opcode_offset)?,
2148 opcodes::LOOKUPSWITCH => read_lookup_switch(&mut reader, opcode_offset)?,
2149 opcodes::IRETURN..=opcodes::RETURN => Insn::Simple(opcode.into()),
2150 opcodes::GETSTATIC..=opcodes::PUTFIELD => Insn::Field(FieldInsnNode {
2151 insn: opcode.into(),
2152 field_ref: MemberRef::Index(reader.read_u2()?),
2153 }),
2154 opcodes::INVOKEVIRTUAL..=opcodes::INVOKESTATIC => Insn::Method(MethodInsnNode {
2155 insn: opcode.into(),
2156 method_ref: MemberRef::Index(reader.read_u2()?),
2157 }),
2158 opcodes::INVOKEINTERFACE => {
2159 let method_index = reader.read_u2()?;
2160 let count = reader.read_u1()?;
2161 let _ = reader.read_u1()?;
2162 Insn::InvokeInterface(InvokeInterfaceInsnNode {
2163 insn: opcode.into(),
2164 method_index,
2165 count,
2166 })
2167 }
2168 opcodes::INVOKEDYNAMIC => {
2169 let method_index = reader.read_u2()?;
2170 let _ = reader.read_u2()?;
2171 Insn::InvokeDynamic(InvokeDynamicInsnNode::from_index(method_index))
2172 }
2173 opcodes::NEW => Insn::Type(TypeInsnNode {
2174 insn: opcode.into(),
2175 type_index: reader.read_u2()?,
2176 }),
2177 opcodes::NEWARRAY => Insn::Int(IntInsnNode {
2178 insn: opcode.into(),
2179 operand: reader.read_u1()? as i32,
2180 }),
2181 opcodes::ANEWARRAY => Insn::Type(TypeInsnNode {
2182 insn: opcode.into(),
2183 type_index: reader.read_u2()?,
2184 }),
2185 opcodes::ARRAYLENGTH | opcodes::ATHROW => Insn::Simple(opcode.into()),
2186 opcodes::CHECKCAST | opcodes::INSTANCEOF => Insn::Type(TypeInsnNode {
2187 insn: opcode.into(),
2188 type_index: reader.read_u2()?,
2189 }),
2190 opcodes::MONITORENTER | opcodes::MONITOREXIT => Insn::Simple(opcode.into()),
2191 opcodes::WIDE => read_wide(&mut reader)?,
2192 opcodes::MULTIANEWARRAY => Insn::MultiANewArray(MultiANewArrayInsnNode {
2193 insn: opcode.into(),
2194 type_index: reader.read_u2()?,
2195 dimensions: reader.read_u1()?,
2196 }),
2197 opcodes::IFNULL | opcodes::IFNONNULL => Insn::Jump(JumpInsnNode {
2198 insn: opcode.into(),
2199 offset: reader.read_i2()? as i32,
2200 }),
2201 opcodes::GOTO_W | opcodes::JSR_W => Insn::Jump(JumpInsnNode {
2202 insn: opcode.into(),
2203 offset: reader.read_i4()?,
2204 }),
2205 opcodes::BREAKPOINT => Insn::Simple(opcode.into()),
2206 opcodes::IMPDEP1 | opcodes::IMPDEP2 => Insn::Simple(opcode.into()),
2207 _ => {
2208 return Err(ClassReadError::InvalidOpcode {
2209 opcode,
2210 offset: opcode_offset,
2211 });
2212 }
2213 };
2214
2215 insns.push(ParsedInstruction {
2216 offset: opcode_offset as u16,
2217 insn,
2218 });
2219 }
2220
2221 Ok(insns)
2222}
2223
2224fn build_insn_nodes(
2225 code: &[u8],
2226 exception_table: &[ExceptionTableEntry],
2227 cp: &[CpInfo],
2228) -> Result<
2229 (
2230 Vec<AbstractInsnNode>,
2231 Vec<TryCatchBlockNode>,
2232 std::collections::HashMap<u16, LabelNode>,
2233 ),
2234 ClassReadError,
2235> {
2236 let instructions = parse_code_instructions_with_offsets(code)?;
2237 let mut offsets = std::collections::HashSet::new();
2238 for instruction in &instructions {
2239 offsets.insert(instruction.offset);
2240 match &instruction.insn {
2241 Insn::Jump(node) => {
2242 offsets.insert((instruction.offset as i32 + node.offset) as u16);
2243 }
2244 Insn::TableSwitch(node) => {
2245 offsets.insert((instruction.offset as i32 + node.default_offset) as u16);
2246 for offset in &node.offsets {
2247 offsets.insert((instruction.offset as i32 + *offset) as u16);
2248 }
2249 }
2250 Insn::LookupSwitch(node) => {
2251 offsets.insert((instruction.offset as i32 + node.default_offset) as u16);
2252 for (_, offset) in &node.pairs {
2253 offsets.insert((instruction.offset as i32 + *offset) as u16);
2254 }
2255 }
2256 _ => {}
2257 }
2258 }
2259 for entry in exception_table {
2260 offsets.insert(entry.start_pc);
2261 offsets.insert(entry.end_pc);
2262 offsets.insert(entry.handler_pc);
2263 }
2264 offsets.insert(code.len() as u16);
2265
2266 let mut label_by_offset = std::collections::HashMap::new();
2267 for (next_id, offset) in offsets.into_iter().enumerate() {
2268 label_by_offset.insert(offset, LabelNode { id: next_id });
2269 }
2270
2271 let mut nodes = Vec::new();
2272 for instruction in instructions {
2273 if let Some(label) = label_by_offset.get(&{ instruction.offset }) {
2274 nodes.push(AbstractInsnNode::Label(*label));
2275 }
2276 nodes.push(AbstractInsnNode::Insn(instruction.insn));
2277 }
2278 if let Some(label) = label_by_offset.get(&(code.len() as u16)) {
2279 nodes.push(AbstractInsnNode::Label(*label));
2280 }
2281
2282 let mut try_catch_blocks = Vec::new();
2283 for entry in exception_table {
2284 let start = *label_by_offset
2285 .get(&entry.start_pc)
2286 .ok_or_else(|| ClassReadError::InvalidAttribute("missing start label".to_string()))?;
2287 let end = *label_by_offset
2288 .get(&entry.end_pc)
2289 .ok_or_else(|| ClassReadError::InvalidAttribute("missing end label".to_string()))?;
2290 let handler = *label_by_offset
2291 .get(&entry.handler_pc)
2292 .ok_or_else(|| ClassReadError::InvalidAttribute("missing handler label".to_string()))?;
2293 let catch_type = if entry.catch_type == 0 {
2294 None
2295 } else {
2296 Some(cp_class_name(cp, entry.catch_type)?.to_string())
2297 };
2298 try_catch_blocks.push(TryCatchBlockNode {
2299 start,
2300 end,
2301 handler,
2302 catch_type,
2303 });
2304 }
2305
2306 Ok((nodes, try_catch_blocks, label_by_offset))
2307}
2308
2309pub(crate) fn build_insn_nodes_public(
2310 code: &[u8],
2311 exception_table: &[ExceptionTableEntry],
2312 cp: &[CpInfo],
2313) -> Result<(Vec<AbstractInsnNode>, Vec<TryCatchBlockNode>), ClassReadError> {
2314 let (nodes, try_catch_blocks, _) = build_insn_nodes(code, exception_table, cp)?;
2315 Ok((nodes, try_catch_blocks))
2316}
2317
2318fn attach_line_numbers(
2319 nodes: Vec<AbstractInsnNode>,
2320 entries: &[LineNumber],
2321 label_by_offset: &std::collections::HashMap<u16, LabelNode>,
2322) -> Vec<AbstractInsnNode> {
2323 let mut lines_by_label = std::collections::HashMap::<usize, Vec<LineNumberInsnNode>>::new();
2324 for entry in entries {
2325 if let Some(label) = label_by_offset.get(&entry.start_pc) {
2326 lines_by_label
2327 .entry(label.id)
2328 .or_default()
2329 .push(LineNumberInsnNode {
2330 line: entry.line_number,
2331 start: *label,
2332 });
2333 }
2334 }
2335
2336 let mut merged = Vec::with_capacity(nodes.len() + entries.len());
2337 for node in nodes {
2338 let label_id = match &node {
2339 AbstractInsnNode::Label(label) => Some(label.id),
2340 _ => None,
2341 };
2342 merged.push(node);
2343 if let Some(label_id) = label_id
2344 && let Some(lines) = lines_by_label.remove(&label_id)
2345 {
2346 for line in lines {
2347 merged.push(AbstractInsnNode::LineNumber(line));
2348 }
2349 }
2350 }
2351 merged
2352}
2353
2354fn read_table_switch(
2355 reader: &mut ByteReader<'_>,
2356 opcode_offset: usize,
2357) -> Result<Insn, ClassReadError> {
2358 reader.align4(opcode_offset)?;
2359 let default_offset = reader.read_i4()?;
2360 let low = reader.read_i4()?;
2361 let high = reader.read_i4()?;
2362 let count = if high < low {
2363 0
2364 } else {
2365 (high - low + 1) as usize
2366 };
2367 let mut offsets = Vec::with_capacity(count);
2368 for _ in 0..count {
2369 offsets.push(reader.read_i4()?);
2370 }
2371 Ok(Insn::TableSwitch(TableSwitchInsnNode {
2372 insn: opcodes::TABLESWITCH.into(),
2373 default_offset,
2374 low,
2375 high,
2376 offsets,
2377 }))
2378}
2379
2380fn read_lookup_switch(
2381 reader: &mut ByteReader<'_>,
2382 opcode_offset: usize,
2383) -> Result<Insn, ClassReadError> {
2384 reader.align4(opcode_offset)?;
2385 let default_offset = reader.read_i4()?;
2386 let npairs = reader.read_i4()? as usize;
2387 let mut pairs = Vec::with_capacity(npairs);
2388 for _ in 0..npairs {
2389 let key = reader.read_i4()?;
2390 let offset = reader.read_i4()?;
2391 pairs.push((key, offset));
2392 }
2393 Ok(Insn::LookupSwitch(LookupSwitchInsnNode {
2394 insn: opcodes::LOOKUPSWITCH.into(),
2395 default_offset,
2396 pairs,
2397 }))
2398}
2399
2400fn read_wide(reader: &mut ByteReader<'_>) -> Result<Insn, ClassReadError> {
2401 let opcode = reader.read_u1()?;
2402 match opcode {
2403 opcodes::ILOAD..=opcodes::ALOAD | opcodes::ISTORE..=opcodes::ASTORE | opcodes::RET => {
2404 Ok(Insn::Var(VarInsnNode {
2405 insn: opcode.into(),
2406 var_index: reader.read_u2()?,
2407 }))
2408 }
2409 opcodes::IINC => Ok(Insn::Iinc(IincInsnNode {
2410 insn: opcode.into(),
2411 var_index: reader.read_u2()?,
2412 increment: reader.read_i2()?,
2413 })),
2414 _ => Err(ClassReadError::InvalidOpcode {
2415 opcode,
2416 offset: reader.pos().saturating_sub(1),
2417 }),
2418 }
2419}
2420
2421fn visit_instruction(
2422 cp: &[CpInfo],
2423 offset: i32,
2424 insn: Insn,
2425 mv: &mut dyn MethodVisitor,
2426) -> Result<(), ClassReadError> {
2427 match insn {
2428 Insn::Simple(node) => {
2429 mv.visit_insn(node.opcode);
2430 }
2431 Insn::Int(node) => {
2432 mv.visit_int_insn(node.insn.opcode, node.operand);
2433 }
2434 Insn::Var(node) => {
2435 mv.visit_var_insn(node.insn.opcode, node.var_index);
2436 }
2437 Insn::Type(node) => {
2438 let type_name = cp_class_name(cp, node.type_index)?;
2439 mv.visit_type_insn(node.insn.opcode, type_name);
2440 }
2441 Insn::Field(node) => {
2442 let index = match node.field_ref {
2443 MemberRef::Index(index) => index,
2444 MemberRef::Symbolic { .. } => {
2445 return Err(ClassReadError::InvalidIndex(0));
2446 }
2447 };
2448 let (owner, name, desc) = cp_field_ref(cp, index)?;
2449 mv.visit_field_insn(node.insn.opcode, owner, name, desc);
2450 }
2451 Insn::Method(node) => {
2452 let index = match node.method_ref {
2453 MemberRef::Index(index) => index,
2454 MemberRef::Symbolic { .. } => {
2455 return Err(ClassReadError::InvalidIndex(0));
2456 }
2457 };
2458 let (owner, name, desc, is_interface) = cp_method_ref(cp, index)?;
2459 mv.visit_method_insn(node.insn.opcode, owner, name, desc, is_interface);
2460 }
2461 Insn::InvokeInterface(node) => {
2462 let (owner, name, desc, _is_interface) = cp_method_ref(cp, node.method_index)?;
2463 mv.visit_method_insn(node.insn.opcode, owner, name, desc, true);
2464 }
2465 Insn::InvokeDynamic(node) => {
2466 let (name, desc) = cp_invoke_dynamic(cp, node.method_index)?;
2467 mv.visit_invoke_dynamic_insn(name, desc);
2468 }
2469 Insn::Jump(node) => {
2470 let target = offset + node.offset;
2471 mv.visit_jump_insn(node.insn.opcode, target);
2472 }
2473 Insn::Ldc(node) => {
2474 let index = match node.value {
2475 LdcValue::Index(index) => index,
2476 LdcValue::String(value) => {
2477 mv.visit_ldc_insn(LdcConstant::String(value));
2478 return Ok(());
2479 }
2480 LdcValue::Type(value) => {
2481 match value.clone() {
2482 Type::Method { .. } => {
2483 mv.visit_ldc_insn(LdcConstant::MethodType(value.get_descriptor()));
2484 }
2485 _ => {
2486 mv.visit_ldc_insn(LdcConstant::Class(value.get_descriptor()));
2487 }
2488 }
2489
2490 return Ok(());
2491 }
2492 LdcValue::Int(value) => {
2493 mv.visit_ldc_insn(LdcConstant::Integer(value));
2494 return Ok(());
2495 }
2496 LdcValue::Float(value) => {
2497 mv.visit_ldc_insn(LdcConstant::Float(value));
2498 return Ok(());
2499 }
2500 LdcValue::Long(value) => {
2501 mv.visit_ldc_insn(LdcConstant::Long(value));
2502 return Ok(());
2503 }
2504 LdcValue::Double(value) => {
2505 mv.visit_ldc_insn(LdcConstant::Double(value));
2506 return Ok(());
2507 }
2508 };
2509 let constant = cp_ldc_constant(cp, index)?;
2510 mv.visit_ldc_insn(constant);
2511 }
2512 Insn::Iinc(node) => {
2513 mv.visit_iinc_insn(node.var_index, node.increment);
2514 }
2515 Insn::TableSwitch(node) => {
2516 let targets = node
2517 .offsets
2518 .iter()
2519 .map(|value| offset + *value)
2520 .collect::<Vec<_>>();
2521 mv.visit_table_switch(offset + node.default_offset, node.low, node.high, &targets);
2522 }
2523 Insn::LookupSwitch(node) => {
2524 let pairs = node
2525 .pairs
2526 .iter()
2527 .map(|(key, value)| (*key, offset + *value))
2528 .collect::<Vec<_>>();
2529 mv.visit_lookup_switch(offset + node.default_offset, &pairs);
2530 }
2531 Insn::MultiANewArray(node) => {
2532 let type_name = cp_class_name(cp, node.type_index)?;
2533 mv.visit_multi_anewarray_insn(type_name, node.dimensions);
2534 }
2535 }
2536 Ok(())
2537}
2538
2539pub struct ByteReader<'a> {
2540 data: &'a [u8],
2541 pos: usize,
2542}
2543
2544impl<'a> ByteReader<'a> {
2545 pub fn new(data: &'a [u8]) -> Self {
2546 Self { data, pos: 0 }
2547 }
2548
2549 pub fn remaining(&self) -> usize {
2550 self.data.len().saturating_sub(self.pos)
2551 }
2552
2553 pub fn pos(&self) -> usize {
2554 self.pos
2555 }
2556
2557 pub fn align4(&mut self, opcode_offset: usize) -> Result<(), ClassReadError> {
2558 let mut padding = (4 - ((opcode_offset + 1) % 4)) % 4;
2559 while padding > 0 {
2560 self.read_u1()?;
2561 padding -= 1;
2562 }
2563 Ok(())
2564 }
2565
2566 pub fn read_u1(&mut self) -> Result<u8, ClassReadError> {
2567 if self.pos >= self.data.len() {
2568 return Err(ClassReadError::UnexpectedEof);
2569 }
2570 let value = self.data[self.pos];
2571 self.pos += 1;
2572 Ok(value)
2573 }
2574
2575 pub fn read_i1(&mut self) -> Result<i8, ClassReadError> {
2576 Ok(self.read_u1()? as i8)
2577 }
2578
2579 pub fn read_u2(&mut self) -> Result<u16, ClassReadError> {
2580 let bytes = self.read_bytes(2)?;
2581 Ok(u16::from_be_bytes([bytes[0], bytes[1]]))
2582 }
2583
2584 pub fn read_i2(&mut self) -> Result<i16, ClassReadError> {
2585 Ok(self.read_u2()? as i16)
2586 }
2587
2588 pub fn read_u4(&mut self) -> Result<u32, ClassReadError> {
2589 let bytes = self.read_bytes(4)?;
2590 Ok(u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
2591 }
2592
2593 pub fn read_i4(&mut self) -> Result<i32, ClassReadError> {
2594 let bytes = self.read_bytes(4)?;
2595 Ok(i32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
2596 }
2597
2598 pub fn read_u8(&mut self) -> Result<u64, ClassReadError> {
2599 let bytes = self.read_bytes(8)?;
2600 Ok(u64::from_be_bytes([
2601 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
2602 ]))
2603 }
2604
2605 pub fn read_bytes(&mut self, len: usize) -> Result<Vec<u8>, ClassReadError> {
2606 if self.pos + len > self.data.len() {
2607 return Err(ClassReadError::UnexpectedEof);
2608 }
2609 let bytes = self.data[self.pos..self.pos + len].to_vec();
2610 self.pos += len;
2611 Ok(bytes)
2612 }
2613}
2614
2615#[cfg(test)]
2616mod tests {
2617 use crate::class_writer::ClassWriter;
2618 use crate::constants::*;
2619 use crate::insn::{Label, LabelNode};
2620 use crate::opcodes;
2621
2622 use super::*;
2623 use std::cell::RefCell;
2624 use std::rc::Rc;
2625
2626 struct MockClassVisitor {
2628 pub visited_name: Rc<RefCell<Option<String>>>,
2629 pub visited_methods: Rc<RefCell<Vec<String>>>,
2630 }
2631
2632 impl MockClassVisitor {
2633 fn new() -> Self {
2634 Self {
2635 visited_name: Rc::new(RefCell::new(None)),
2636 visited_methods: Rc::new(RefCell::new(Vec::new())),
2637 }
2638 }
2639 }
2640
2641 impl ClassVisitor for MockClassVisitor {
2642 fn visit(
2643 &mut self,
2644 _major: u16,
2645 _minor: u16,
2646 _access_flags: u16,
2647 name: &str,
2648 _super_name: Option<&str>,
2649 _interfaces: &[String],
2650 ) {
2651 *self.visited_name.borrow_mut() = Some(name.to_string());
2652 }
2653
2654 fn visit_method(
2655 &mut self,
2656 _access_flags: u16,
2657 name: &str,
2658 _descriptor: &str,
2659 ) -> Option<Box<dyn MethodVisitor>> {
2660 self.visited_methods.borrow_mut().push(name.to_string());
2661 None
2662 }
2663 }
2664
2665 fn generate_minimal_class() -> Vec<u8> {
2668 let mut w = Vec::new();
2669 w.extend_from_slice(&0xCAFEBABE_u32.to_be_bytes());
2671 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);
2684 let name = "TestClass";
2685 w.extend_from_slice(&(name.len() as u16).to_be_bytes());
2686 w.extend_from_slice(name.as_bytes());
2687
2688 w.push(7);
2690 w.extend_from_slice(&1_u16.to_be_bytes());
2691
2692 w.push(1);
2694 let obj = "java/lang/Object";
2695 w.extend_from_slice(&(obj.len() as u16).to_be_bytes());
2696 w.extend_from_slice(obj.as_bytes());
2697
2698 w.push(7);
2700 w.extend_from_slice(&3_u16.to_be_bytes());
2701
2702 w.extend_from_slice(&0x0021_u16.to_be_bytes());
2704 w.extend_from_slice(&2_u16.to_be_bytes());
2706 w.extend_from_slice(&4_u16.to_be_bytes());
2708
2709 w.extend_from_slice(&0_u16.to_be_bytes());
2711 w.extend_from_slice(&0_u16.to_be_bytes());
2713 w.extend_from_slice(&0_u16.to_be_bytes());
2715 w.extend_from_slice(&0_u16.to_be_bytes());
2717
2718 w
2719 }
2720
2721 fn generate_module_info_class() -> Vec<u8> {
2722 let mut writer = ClassWriter::new(0);
2723 writer.visit(V9, 0, ACC_MODULE, "module-info", None, &[]);
2724
2725 let mut module = writer.visit_module("com.example.app", ACC_OPEN, Some("1.0"));
2726 module.visit_main_class("com/example/app/Main");
2727 module.visit_package("com/example/api");
2728 module.visit_package("com/example/internal");
2729 module.visit_require("java.base", ACC_MANDATED, None);
2730 module.visit_require(
2731 "com.example.lib",
2732 ACC_TRANSITIVE | ACC_STATIC_PHASE,
2733 Some("2.1"),
2734 );
2735 module.visit_export("com/example/api", 0, &["com.example.consumer"]);
2736 module.visit_open("com/example/internal", 0, &["com.example.runtime"]);
2737 module.visit_use("com/example/spi/Service");
2738 module.visit_provide("com/example/spi/Service", &["com/example/impl/ServiceImpl"]);
2739 module.visit_end(&mut writer);
2740
2741 writer.to_bytes().expect("module-info should encode")
2742 }
2743
2744 #[test]
2745 fn test_class_reader_header() {
2746 let bytes = generate_minimal_class();
2747 let reader = ClassReader::new(&bytes);
2748 let mut visitor = MockClassVisitor::new();
2749
2750 let result = reader.accept(&mut visitor, 0);
2751
2752 assert!(result.is_ok(), "Should parse valid class file");
2753 assert_eq!(
2754 *visitor.visited_name.borrow(),
2755 Some("TestClass".to_string())
2756 );
2757 }
2758
2759 #[test]
2760 fn test_invalid_magic() {
2761 let bytes = vec![0x00, 0x00, 0x00, 0x00];
2763 let reader = ClassReader::new(&bytes);
2764 let mut visitor = MockClassVisitor::new();
2765
2766 let result = reader.accept(&mut visitor, 0);
2767 assert!(matches!(result, Err(ClassReadError::InvalidMagic(_))));
2768 }
2769
2770 #[test]
2771 fn test_code_reader_alignment() {
2772 let data = vec![0x00, 0x00, 0x00, 0x00]; let mut reader = super::ByteReader::new(&data);
2775
2776 reader.pos = 1;
2778 assert!(reader.align4(0).is_ok());
2780 assert_eq!(reader.pos(), 4);
2781 }
2782
2783 #[test]
2784 fn test_parse_runtime_visible_type_annotations_supertype() {
2785 let mut info = vec![];
2795 u2(1, &mut info);
2796 u1(TA_TARGET_CLASS_EXTENDS, &mut info);
2797 u2(5, &mut info);
2798 u1(0, &mut info);
2799 u2(10, &mut info);
2800 u2(0, &mut info);
2801
2802 let cp: Vec<CpInfo> = vec![];
2803 let attr = parse_attribute("RuntimeVisibleTypeAnnotations", info, &cp).unwrap();
2804
2805 match attr {
2806 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations } => {
2807 assert_eq!(annotations.len(), 1);
2808 let a = &annotations[0];
2809 assert_eq!(a.target_type, TA_TARGET_CLASS_EXTENDS);
2810 assert!(matches!(
2811 a.target_info,
2812 TypeAnnotationTargetInfo::Supertype { supertype_index: 5 }
2813 ));
2814 assert_eq!(a.target_path.path.len(), 0);
2815 assert_eq!(a.annotation.type_descriptor_index, 10);
2816 assert_eq!(a.annotation.element_value_pairs.len(), 0);
2817 }
2818 other => panic!("unexpected attr: {:?}", other),
2819 }
2820 }
2821
2822 #[test]
2823 fn test_parse_runtime_visible_type_annotations_formal_parameter_with_path() {
2824 let mut info = vec![];
2829 u2(1, &mut info);
2830 u1(TA_TARGET_METHOD_FORMAL_PARAMETER, &mut info);
2831 u1(2, &mut info);
2832
2833 u1(1, &mut info); u1(TA_TYPE_PATH_ARRAY, &mut info);
2835 u1(0, &mut info);
2836
2837 u2(9, &mut info);
2838 u2(0, &mut info);
2839
2840 let cp: Vec<CpInfo> = vec![];
2841 let attr = parse_attribute("RuntimeVisibleTypeAnnotations", info, &cp).unwrap();
2842
2843 match attr {
2844 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations } => {
2845 let a = &annotations[0];
2846 assert_eq!(a.target_type, TA_TARGET_METHOD_FORMAL_PARAMETER);
2847 assert!(matches!(
2848 a.target_info,
2849 TypeAnnotationTargetInfo::FormalParameter {
2850 formal_parameter_index: 2
2851 }
2852 ));
2853 assert_eq!(a.target_path.path.len(), 1);
2854 assert_eq!(a.target_path.path[0].type_path_kind, TA_TYPE_PATH_ARRAY);
2855 assert_eq!(a.target_path.path[0].type_argument_index, 0);
2856 }
2857 other => panic!("unexpected attr: {:?}", other),
2858 }
2859 }
2860
2861 #[test]
2862 fn test_parse_runtime_visible_type_annotations_localvar_table() {
2863 let mut info = vec![];
2869 u2(1, &mut info);
2870 u1(TA_TARGET_LOCAL_VARIABLE, &mut info);
2871
2872 u2(1, &mut info); u2(1, &mut info);
2874 u2(2, &mut info);
2875 u2(3, &mut info);
2876
2877 u1(0, &mut info); u2(8, &mut info);
2879 u2(0, &mut info);
2880
2881 let cp: Vec<CpInfo> = vec![];
2882 let attr = parse_attribute("RuntimeVisibleTypeAnnotations", info, &cp).unwrap();
2883
2884 match attr {
2885 AttributeInfo::RuntimeVisibleTypeAnnotations { annotations } => {
2886 let a = &annotations[0];
2887 assert_eq!(a.target_type, TA_TARGET_LOCAL_VARIABLE);
2888 match &a.target_info {
2889 TypeAnnotationTargetInfo::LocalVar { table } => {
2890 assert_eq!(table.len(), 1);
2891 assert_eq!(table[0].start_pc, 1);
2892 assert_eq!(table[0].length, 2);
2893 assert_eq!(table[0].index, 3);
2894 }
2895 other => panic!("unexpected target_info: {:?}", other),
2896 }
2897 }
2898 other => panic!("unexpected attr: {:?}", other),
2899 }
2900 }
2901
2902 #[test]
2903 fn test_parse_module_attribute_family() {
2904 let mut module_info = vec![];
2905 u2(1, &mut module_info);
2906 u2(ACC_OPEN, &mut module_info);
2907 u2(2, &mut module_info);
2908 u2(1, &mut module_info);
2909 u2(3, &mut module_info);
2910 u2(ACC_TRANSITIVE | ACC_STATIC_PHASE, &mut module_info);
2911 u2(4, &mut module_info);
2912 u2(1, &mut module_info);
2913 u2(5, &mut module_info);
2914 u2(ACC_MANDATED, &mut module_info);
2915 u2(2, &mut module_info);
2916 u2(6, &mut module_info);
2917 u2(7, &mut module_info);
2918 u2(1, &mut module_info);
2919 u2(8, &mut module_info);
2920 u2(0, &mut module_info);
2921 u2(1, &mut module_info);
2922 u2(9, &mut module_info);
2923 u2(1, &mut module_info);
2924 u2(10, &mut module_info);
2925 u2(1, &mut module_info);
2926 u2(11, &mut module_info);
2927 u2(2, &mut module_info);
2928 u2(12, &mut module_info);
2929 u2(13, &mut module_info);
2930
2931 let attr = parse_attribute("Module", module_info, &[]).expect("module attr should parse");
2932 match attr {
2933 AttributeInfo::Module(module) => {
2934 assert_eq!(module.module_name_index, 1);
2935 assert_eq!(module.module_flags, ACC_OPEN);
2936 assert_eq!(module.module_version_index, 2);
2937 assert_eq!(
2938 module.requires,
2939 vec![ModuleRequire {
2940 requires_index: 3,
2941 requires_flags: ACC_TRANSITIVE | ACC_STATIC_PHASE,
2942 requires_version_index: 4,
2943 }]
2944 );
2945 assert_eq!(
2946 module.exports,
2947 vec![ModuleExport {
2948 exports_index: 5,
2949 exports_flags: ACC_MANDATED,
2950 exports_to_index: vec![6, 7],
2951 }]
2952 );
2953 assert_eq!(
2954 module.opens,
2955 vec![ModuleOpen {
2956 opens_index: 8,
2957 opens_flags: 0,
2958 opens_to_index: vec![9],
2959 }]
2960 );
2961 assert_eq!(module.uses_index, vec![10]);
2962 assert_eq!(
2963 module.provides,
2964 vec![ModuleProvide {
2965 provides_index: 11,
2966 provides_with_index: vec![12, 13],
2967 }]
2968 );
2969 }
2970 other => panic!("unexpected attr: {:?}", other),
2971 }
2972
2973 let mut packages_info = vec![];
2974 u2(2, &mut packages_info);
2975 u2(21, &mut packages_info);
2976 u2(22, &mut packages_info);
2977 let attr = parse_attribute("ModulePackages", packages_info, &[])
2978 .expect("module packages attr should parse");
2979 match attr {
2980 AttributeInfo::ModulePackages {
2981 package_index_table,
2982 } => {
2983 assert_eq!(package_index_table, vec![21, 22]);
2984 }
2985 other => panic!("unexpected attr: {:?}", other),
2986 }
2987
2988 let mut main_class_info = vec![];
2989 u2(23, &mut main_class_info);
2990 let attr = parse_attribute("ModuleMainClass", main_class_info, &[])
2991 .expect("module main class attr should parse");
2992 match attr {
2993 AttributeInfo::ModuleMainClass { main_class_index } => {
2994 assert_eq!(main_class_index, 23);
2995 }
2996 other => panic!("unexpected attr: {:?}", other),
2997 }
2998 }
2999
3000 fn u1(v: u8, out: &mut Vec<u8>) {
3001 out.push(v);
3002 }
3003 fn u2(v: u16, out: &mut Vec<u8>) {
3004 out.extend_from_slice(&v.to_be_bytes());
3005 }
3006
3007 #[test]
3008 fn test_method_node_contains_offsets_and_line_numbers() {
3009 let mut writer = ClassWriter::new(0);
3010 writer.visit(
3011 52,
3012 0,
3013 ACC_PUBLIC,
3014 "TestNodeData",
3015 Some("java/lang/Object"),
3016 &[],
3017 );
3018
3019 let mut ctor = writer.visit_method(ACC_PUBLIC, "<init>", "()V");
3020 ctor.visit_code();
3021 ctor.visit_var_insn(opcodes::ALOAD, 0);
3022 ctor.visit_method_insn(
3023 opcodes::INVOKESPECIAL,
3024 "java/lang/Object",
3025 "<init>",
3026 "()V",
3027 false,
3028 );
3029 ctor.visit_insn(opcodes::RETURN);
3030 ctor.visit_maxs(1, 1);
3031 ctor.visit_end(&mut writer);
3032
3033 let mut method = writer.visit_method(ACC_PUBLIC | ACC_STATIC, "answer", "()I");
3034 let start = Label::new();
3035 method.visit_code();
3036 method.visit_label(start);
3037 method.visit_line_number(123, LabelNode::from_label(start));
3038 method.visit_insn(opcodes::ICONST_1);
3039 method.visit_insn(opcodes::IRETURN);
3040 method.visit_maxs(1, 0);
3041 method.visit_end(&mut writer);
3042
3043 let bytes = writer.to_bytes().expect("class should encode");
3044 let class = ClassReader::new(&bytes)
3045 .to_class_node()
3046 .expect("class should decode");
3047 let method = class
3048 .methods
3049 .iter()
3050 .find(|method| method.name == "answer")
3051 .expect("method should exist");
3052
3053 assert_eq!(method.instruction_offsets, vec![0, 1]);
3054 assert_eq!(method.line_numbers.len(), 1);
3055 assert_eq!(method.line_numbers[0].line_number, 123);
3056 assert!(
3057 method
3058 .insn_nodes
3059 .iter()
3060 .any(|node| matches!(node, AbstractInsnNode::LineNumber(_)))
3061 );
3062 assert!(
3063 method
3064 .insn_nodes
3065 .iter()
3066 .any(|node| matches!(node, AbstractInsnNode::Label(_)))
3067 );
3068 assert!(method.try_catch_blocks.is_empty());
3069 }
3070
3071 #[test]
3072 fn test_method_node_contains_try_catch_blocks() {
3073 let mut writer = ClassWriter::new(0);
3074 writer.visit(
3075 52,
3076 0,
3077 ACC_PUBLIC,
3078 "TestTryCatchNode",
3079 Some("java/lang/Object"),
3080 &[],
3081 );
3082
3083 let mut ctor = writer.visit_method(ACC_PUBLIC, "<init>", "()V");
3084 ctor.visit_code();
3085 ctor.visit_var_insn(opcodes::ALOAD, 0);
3086 ctor.visit_method_insn(
3087 opcodes::INVOKESPECIAL,
3088 "java/lang/Object",
3089 "<init>",
3090 "()V",
3091 false,
3092 );
3093 ctor.visit_insn(opcodes::RETURN);
3094 ctor.visit_maxs(1, 1);
3095 ctor.visit_end(&mut writer);
3096
3097 let start = Label::new();
3098 let end = Label::new();
3099 let handler = Label::new();
3100 let mut method =
3101 writer.visit_method(ACC_PUBLIC | ACC_STATIC, "safeLen", "(Ljava/lang/String;)I");
3102 method.visit_code();
3103 method.visit_label(start);
3104 method.visit_var_insn(opcodes::ALOAD, 0);
3105 method.visit_method_insn(
3106 opcodes::INVOKEVIRTUAL,
3107 "java/lang/String",
3108 "length",
3109 "()I",
3110 false,
3111 );
3112 method.visit_insn(opcodes::IRETURN);
3113 method.visit_label(end);
3114 method.visit_label(handler);
3115 method.visit_var_insn(opcodes::ASTORE, 1);
3116 method.visit_insn(opcodes::ICONST_M1);
3117 method.visit_insn(opcodes::IRETURN);
3118 method.visit_try_catch_block(start, end, handler, Some("java/lang/RuntimeException"));
3119 method.visit_maxs(1, 2);
3120 method.visit_end(&mut writer);
3121
3122 let bytes = writer.to_bytes().expect("class should encode");
3123 let class = ClassReader::new(&bytes)
3124 .to_class_node()
3125 .expect("class should decode");
3126 let method = class
3127 .methods
3128 .iter()
3129 .find(|method| method.name == "safeLen")
3130 .expect("method should exist");
3131
3132 assert_eq!(method.exception_table.len(), 1);
3133 assert_eq!(method.try_catch_blocks.len(), 1);
3134 assert_eq!(
3135 method.try_catch_blocks[0].catch_type.as_deref(),
3136 Some("java/lang/RuntimeException")
3137 );
3138 }
3139
3140 #[test]
3141 fn test_parse_runtime_visible_annotations_one_empty() {
3142 let mut info = vec![];
3145 u2(1, &mut info);
3146 u2(10, &mut info);
3147 u2(0, &mut info);
3148
3149 let cp: Vec<CpInfo> = vec![];
3150 let attr = parse_attribute("RuntimeVisibleAnnotations", info, &cp).unwrap();
3151 match attr {
3152 AttributeInfo::RuntimeVisibleAnnotations { annotations } => {
3153 assert_eq!(annotations.len(), 1);
3154 assert_eq!(annotations[0].type_descriptor_index, 10);
3155 assert_eq!(annotations[0].element_value_pairs.len(), 0);
3156 }
3157 other => panic!("unexpected attr: {:?}", other),
3158 }
3159 }
3160
3161 #[test]
3162 fn test_parse_runtime_visible_parameter_annotations_two_params() {
3163 let mut info = vec![];
3167 u1(2, &mut info);
3168 u2(1, &mut info);
3169 u2(10, &mut info);
3170 u2(0, &mut info);
3171 u2(0, &mut info);
3172
3173 let cp: Vec<CpInfo> = vec![];
3174 let attr = parse_attribute("RuntimeVisibleParameterAnnotations", info, &cp).unwrap();
3175 match attr {
3176 AttributeInfo::RuntimeVisibleParameterAnnotations { parameters } => {
3177 assert_eq!(parameters.parameters.len(), 2);
3178 assert_eq!(parameters.parameters[0].len(), 1);
3179 assert_eq!(parameters.parameters[1].len(), 0);
3180 }
3181 other => panic!("unexpected attr: {:?}", other),
3182 }
3183 }
3184
3185 #[test]
3186 fn test_class_reader_decodes_module_info_node() {
3187 let bytes = generate_module_info_class();
3188 let class = ClassReader::new(&bytes)
3189 .to_class_node()
3190 .expect("module-info should decode");
3191
3192 assert_eq!(class.name, "module-info");
3193 assert_eq!(class.access_flags, ACC_MODULE);
3194
3195 let module = class.module.expect("module descriptor should be decoded");
3196 assert_eq!(module.name, "com.example.app");
3197 assert_eq!(module.access_flags, ACC_OPEN);
3198 assert_eq!(module.version.as_deref(), Some("1.0"));
3199 assert_eq!(module.main_class.as_deref(), Some("com/example/app/Main"));
3200 assert_eq!(
3201 module.packages,
3202 vec![
3203 "com/example/api".to_string(),
3204 "com/example/internal".to_string()
3205 ]
3206 );
3207 assert_eq!(module.requires.len(), 2);
3208 assert_eq!(module.requires[0].module, "java.base");
3209 assert_eq!(module.requires[0].access_flags, ACC_MANDATED);
3210 assert_eq!(module.requires[0].version, None);
3211 assert_eq!(module.requires[1].module, "com.example.lib");
3212 assert_eq!(
3213 module.requires[1].access_flags,
3214 ACC_TRANSITIVE | ACC_STATIC_PHASE
3215 );
3216 assert_eq!(module.requires[1].version.as_deref(), Some("2.1"));
3217 assert_eq!(module.exports.len(), 1);
3218 assert_eq!(module.exports[0].package, "com/example/api");
3219 assert_eq!(
3220 module.exports[0].modules,
3221 vec!["com.example.consumer".to_string()]
3222 );
3223 assert_eq!(module.opens.len(), 1);
3224 assert_eq!(module.opens[0].package, "com/example/internal");
3225 assert_eq!(
3226 module.opens[0].modules,
3227 vec!["com.example.runtime".to_string()]
3228 );
3229 assert_eq!(module.uses, vec!["com/example/spi/Service".to_string()]);
3230 assert_eq!(module.provides.len(), 1);
3231 assert_eq!(module.provides[0].service, "com/example/spi/Service");
3232 assert_eq!(
3233 module.provides[0].providers,
3234 vec!["com/example/impl/ServiceImpl".to_string()]
3235 );
3236 }
3237}