classfile: model RuntimeVisible/InvisibleParameterAnnotations (fixes ASM AIOOBE on write)
Parameter annotations were unmodeled and fell through to Raw with stale constant-pool indices after the pool rebuild. ASM (Paper converter, Fabric mixin transformer) then failed with ArrayIndexOutOfBoundsException in readParameterAnnotations. Now parsed and rewritten like class-level annotations.
This commit is contained in:
parent
045cd3ed9c
commit
b73c72d56d
5 changed files with 80 additions and 1 deletions
|
|
@ -123,6 +123,36 @@ pub(super) fn convert(attr: &RtAttr, pool: &ConstantPool<'_>) -> Result<Attribut
|
|||
.collect::<Result<_, _>>()?,
|
||||
)
|
||||
}
|
||||
RtAttr::RuntimeVisibleParameterAnnotations {
|
||||
parameter_annotations,
|
||||
..
|
||||
} => Attribute::RuntimeVisibleParameterAnnotations(
|
||||
parameter_annotations
|
||||
.iter()
|
||||
.map(|param| {
|
||||
param
|
||||
.annotations
|
||||
.iter()
|
||||
.map(|anno| annotation(pool, anno))
|
||||
.collect::<Result<_, _>>()
|
||||
})
|
||||
.collect::<Result<_, _>>()?,
|
||||
),
|
||||
RtAttr::RuntimeInvisibleParameterAnnotations {
|
||||
parameter_annotations,
|
||||
..
|
||||
} => Attribute::RuntimeInvisibleParameterAnnotations(
|
||||
parameter_annotations
|
||||
.iter()
|
||||
.map(|param| {
|
||||
param
|
||||
.annotations
|
||||
.iter()
|
||||
.map(|anno| annotation(pool, anno))
|
||||
.collect::<Result<_, _>>()
|
||||
})
|
||||
.collect::<Result<_, _>>()?,
|
||||
),
|
||||
other => raw(other)?,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,6 +193,38 @@ pub(super) fn convert(attr: &Attribute, pool: &mut Pool) -> Result<RtAttr, Class
|
|||
.map(|anno| annotation(anno, pool))
|
||||
.collect::<Result<_, _>>()?,
|
||||
},
|
||||
Attribute::RuntimeVisibleParameterAnnotations(params) => {
|
||||
RtAttr::RuntimeVisibleParameterAnnotations {
|
||||
name_index: pool.utf8("RuntimeVisibleParameterAnnotations")?,
|
||||
parameter_annotations: params
|
||||
.iter()
|
||||
.map(|param| {
|
||||
Ok(ristretto_classfile::attributes::ParameterAnnotation {
|
||||
annotations: param
|
||||
.iter()
|
||||
.map(|anno| annotation(anno, pool))
|
||||
.collect::<Result<_, _>>()?,
|
||||
})
|
||||
})
|
||||
.collect::<Result<_, _>>()?,
|
||||
}
|
||||
}
|
||||
Attribute::RuntimeInvisibleParameterAnnotations(params) => {
|
||||
RtAttr::RuntimeInvisibleParameterAnnotations {
|
||||
name_index: pool.utf8("RuntimeInvisibleParameterAnnotations")?,
|
||||
parameter_annotations: params
|
||||
.iter()
|
||||
.map(|param| {
|
||||
Ok(ristretto_classfile::attributes::ParameterAnnotation {
|
||||
annotations: param
|
||||
.iter()
|
||||
.map(|anno| annotation(anno, pool))
|
||||
.collect::<Result<_, _>>()?,
|
||||
})
|
||||
})
|
||||
.collect::<Result<_, _>>()?,
|
||||
}
|
||||
}
|
||||
Attribute::Raw { name, data } => RtAttr::Unknown {
|
||||
name_index: pool.utf8(name)?,
|
||||
info: data.clone(),
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@ pub enum Attribute {
|
|||
RuntimeVisibleAnnotations(Vec<Annotation>),
|
||||
/// `RuntimeInvisibleAnnotations` (JVMS §4.7.17): CLASS-retention ones.
|
||||
RuntimeInvisibleAnnotations(Vec<Annotation>),
|
||||
/// `RuntimeVisibleParameterAnnotations` (JVMS §4.7.18): per-parameter
|
||||
/// annotations. Parsed like the class-level ones - raw pool indices go
|
||||
/// stale when the pool is rebuilt.
|
||||
RuntimeVisibleParameterAnnotations(Vec<Vec<Annotation>>),
|
||||
/// `RuntimeInvisibleParameterAnnotations` (JVMS §4.7.19).
|
||||
RuntimeInvisibleParameterAnnotations(Vec<Vec<Annotation>>),
|
||||
/// Everything else: name + raw `info` bytes (careful with pool indices).
|
||||
Raw {
|
||||
name: String,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@ pub(super) fn rewrite_annotations(annotations: &mut [Annotation], maps: &RenameM
|
|||
}
|
||||
}
|
||||
|
||||
/// Per-parameter annotation lists (`RuntimeVisibleParameterAnnotations`).
|
||||
pub(super) fn rewrite_parameter_annotations(params: &mut [Vec<Annotation>], maps: &RenameMaps) {
|
||||
for param in params.iter_mut() {
|
||||
rewrite_annotations(param, maps);
|
||||
}
|
||||
}
|
||||
|
||||
fn rewrite_annotation(anno: &mut Annotation, maps: &RenameMaps) {
|
||||
anno.descriptor = rewrite_descriptor(&anno.descriptor, &maps.classes);
|
||||
for (_, value) in anno.elements.iter_mut() {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
mod annotations;
|
||||
mod code;
|
||||
|
||||
use annotations::rewrite_annotations;
|
||||
use annotations::{rewrite_annotations, rewrite_parameter_annotations};
|
||||
use noxis_classfile::{Attribute, ClassFile, Const, StackMapFrame, VerificationType};
|
||||
use noxis_core::{Config, Context};
|
||||
|
||||
|
|
@ -147,6 +147,10 @@ fn rewrite_attributes(
|
|||
| Attribute::RuntimeInvisibleAnnotations(annos) => {
|
||||
rewrite_annotations(annos, maps);
|
||||
}
|
||||
Attribute::RuntimeVisibleParameterAnnotations(params)
|
||||
| Attribute::RuntimeInvisibleParameterAnnotations(params) => {
|
||||
rewrite_parameter_annotations(params, maps);
|
||||
}
|
||||
Attribute::BootstrapMethods(methods) => {
|
||||
for bsm in methods.iter_mut() {
|
||||
rewrite_method_ref(&mut bsm.owner, &mut bsm.name, &mut bsm.descriptor, maps);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue