Skip to content

Commit

Permalink
Fix: Fix interface injector visibility checks. (#156)
Browse files Browse the repository at this point in the history
`InjectionInfo.parse` can be very expensive and in the case of some MixinExtras features is not pure.
The correct approach would be to use `InjectionInfo.getInjectorAnnotation`, but the override is no longer needed anyway since we only support Java 8+ so Mixin will already make injector methods private and synthetic.
Except, Mixin does it based on the current `COMPATIBILITY_LEVEL`, which is wrong, because we could be on JAVA_17 and yet a class compiled with JAVA_8 had no choice but to use public methods.
The original implementation was also incomplete because it forgot about default methods.
  • Loading branch information
LlamaLad7 authored Sep 3, 2024
1 parent adcd952 commit c3e6d66
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 20 deletions.
12 changes: 11 additions & 1 deletion src/main/java/org/spongepowered/asm/mixin/MixinEnvironment.java
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,17 @@ static String getSupportedVersions() {
}
return sb.toString();
}


public static CompatibilityLevel forClassVersion(int version) {
CompatibilityLevel latest = null;
for (CompatibilityLevel level : values()) {
if (level.getClassVersion() >= version) {
return level;
}
latest = level;
}
return latest;
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,17 @@
*/
package org.spongepowered.asm.mixin.transformer;

import java.lang.reflect.Modifier;
import java.util.Map.Entry;

import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.MixinEnvironment.Feature;
import org.spongepowered.asm.mixin.injection.struct.InjectionInfo;
import org.spongepowered.asm.mixin.injection.throwables.InvalidInjectionException;
import org.spongepowered.asm.mixin.transformer.ClassInfo.Field;
import org.spongepowered.asm.mixin.transformer.throwables.InvalidInterfaceMixinException;
import org.spongepowered.asm.util.Annotations;
import org.spongepowered.asm.util.Constants;
import org.spongepowered.asm.util.LanguageFeatures;

/**
* Applicator for interface mixins, mainly just disables things which aren't
Expand Down Expand Up @@ -166,17 +163,4 @@ protected void applyInjections(MixinTargetContext mixin, int injectorOrder) {
return;
}
}

@Override
protected void checkMethodVisibility(MixinTargetContext mixin, MethodNode mixinMethod) {
//Allow injecting into static interface methods where it isn't possible to control the access of the injection method
if (Modifier.isStatic(mixinMethod.access) && !MixinEnvironment.getCompatibilityLevel().supports(LanguageFeatures.PRIVATE_METHODS_IN_INTERFACES)) {
InjectionInfo injectInfo = InjectionInfo.parse(mixin, mixinMethod);
if (injectInfo != null) {
return;
}
}

super.checkMethodVisibility(mixin, mixinMethod);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1268,6 +1268,10 @@ List<ClassInfo> getTargets() {
Set<String> getInterfaces() {
return this.getState().getInterfaces();
}

int getClassVersion() {
return this.getState().getClassNode().version;
}

/**
* Get transformer extensions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,11 @@ protected void prepareMethod(MixinMethodNode mixinMethod, Method method) {
method, this.mixin));
}

// Make injectors private synthetic if the current runtime supports it
CompatibilityLevel classLevel = CompatibilityLevel.forClassVersion(mixin.getClassVersion());
// Make injectors private synthetic if the current class version supports it
if (isPublic
&& !currentLevel.supports(LanguageFeatures.PRIVATE_METHODS_IN_INTERFACES)
&& currentLevel.supports(LanguageFeatures.PRIVATE_SYNTHETIC_METHODS_IN_INTERFACES)) {
&& !classLevel.supports(LanguageFeatures.PRIVATE_METHODS_IN_INTERFACES)
&& classLevel.supports(LanguageFeatures.PRIVATE_SYNTHETIC_METHODS_IN_INTERFACES)) {
Bytecode.setVisibility(mixinMethod, Bytecode.Visibility.PRIVATE);
mixinMethod.access |= Opcodes.ACC_SYNTHETIC;
}
Expand Down

0 comments on commit c3e6d66

Please sign in to comment.