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<_, _>>()?,
|
.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)?,
|
other => raw(other)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,38 @@ pub(super) fn convert(attr: &Attribute, pool: &mut Pool) -> Result<RtAttr, Class
|
||||||
.map(|anno| annotation(anno, pool))
|
.map(|anno| annotation(anno, pool))
|
||||||
.collect::<Result<_, _>>()?,
|
.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 {
|
Attribute::Raw { name, data } => RtAttr::Unknown {
|
||||||
name_index: pool.utf8(name)?,
|
name_index: pool.utf8(name)?,
|
||||||
info: data.clone(),
|
info: data.clone(),
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,12 @@ pub enum Attribute {
|
||||||
RuntimeVisibleAnnotations(Vec<Annotation>),
|
RuntimeVisibleAnnotations(Vec<Annotation>),
|
||||||
/// `RuntimeInvisibleAnnotations` (JVMS §4.7.17): CLASS-retention ones.
|
/// `RuntimeInvisibleAnnotations` (JVMS §4.7.17): CLASS-retention ones.
|
||||||
RuntimeInvisibleAnnotations(Vec<Annotation>),
|
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).
|
/// Everything else: name + raw `info` bytes (careful with pool indices).
|
||||||
Raw {
|
Raw {
|
||||||
name: String,
|
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) {
|
fn rewrite_annotation(anno: &mut Annotation, maps: &RenameMaps) {
|
||||||
anno.descriptor = rewrite_descriptor(&anno.descriptor, &maps.classes);
|
anno.descriptor = rewrite_descriptor(&anno.descriptor, &maps.classes);
|
||||||
for (_, value) in anno.elements.iter_mut() {
|
for (_, value) in anno.elements.iter_mut() {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
mod annotations;
|
mod annotations;
|
||||||
mod code;
|
mod code;
|
||||||
|
|
||||||
use annotations::rewrite_annotations;
|
use annotations::{rewrite_annotations, rewrite_parameter_annotations};
|
||||||
use noxis_classfile::{Attribute, ClassFile, Const, StackMapFrame, VerificationType};
|
use noxis_classfile::{Attribute, ClassFile, Const, StackMapFrame, VerificationType};
|
||||||
use noxis_core::{Config, Context};
|
use noxis_core::{Config, Context};
|
||||||
|
|
||||||
|
|
@ -147,6 +147,10 @@ fn rewrite_attributes(
|
||||||
| Attribute::RuntimeInvisibleAnnotations(annos) => {
|
| Attribute::RuntimeInvisibleAnnotations(annos) => {
|
||||||
rewrite_annotations(annos, maps);
|
rewrite_annotations(annos, maps);
|
||||||
}
|
}
|
||||||
|
Attribute::RuntimeVisibleParameterAnnotations(params)
|
||||||
|
| Attribute::RuntimeInvisibleParameterAnnotations(params) => {
|
||||||
|
rewrite_parameter_annotations(params, maps);
|
||||||
|
}
|
||||||
Attribute::BootstrapMethods(methods) => {
|
Attribute::BootstrapMethods(methods) => {
|
||||||
for bsm in methods.iter_mut() {
|
for bsm in methods.iter_mut() {
|
||||||
rewrite_method_ref(&mut bsm.owner, &mut bsm.name, &mut bsm.descriptor, maps);
|
rewrite_method_ref(&mut bsm.owner, &mut bsm.name, &mut bsm.descriptor, maps);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue