Merge pull request #31 from yushijinhun/mc52974

实现 #30
This commit is contained in:
Haowei Wen 2019-01-19 21:10:00 +08:00 committed by GitHub
commit e31f1f7392
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 276 additions and 0 deletions

View file

@ -23,6 +23,7 @@ import static java.util.Optional.of;
import static moe.yushi.authlibinjector.util.IOUtils.asBytes;
import static moe.yushi.authlibinjector.util.IOUtils.asString;
import static moe.yushi.authlibinjector.util.IOUtils.removeNewLines;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.instrument.ClassFileTransformer;
@ -48,10 +49,12 @@ import moe.yushi.authlibinjector.transform.AuthlibLogInterceptor;
import moe.yushi.authlibinjector.transform.ClassTransformer;
import moe.yushi.authlibinjector.transform.ConstantURLTransformUnit;
import moe.yushi.authlibinjector.transform.DumpClassListener;
import moe.yushi.authlibinjector.transform.MainArgumentsTransformer;
import moe.yushi.authlibinjector.transform.SkinWhitelistTransformUnit;
import moe.yushi.authlibinjector.transform.YggdrasilKeyTransformUnit;
import moe.yushi.authlibinjector.transform.support.CitizensTransformer;
import moe.yushi.authlibinjector.transform.support.LaunchWrapperTransformer;
import moe.yushi.authlibinjector.transform.support.MC52974Workaround;
import moe.yushi.authlibinjector.util.Logging;
import moe.yushi.authlibinjector.yggdrasil.CustomYggdrasilAPIProvider;
import moe.yushi.authlibinjector.yggdrasil.MojangYggdrasilAPIProvider;
@ -312,6 +315,11 @@ public final class AuthlibInjector {
filters.add(new QueryUUIDsFilter(mojangClient, customClient));
filters.add(new QueryProfileFilter(mojangClient, customClient));
MainArgumentsTransformer.getListeners().add(args -> {
MC52974Workaround.acceptMainArguments(args);
return args;
});
return filters;
}
@ -331,8 +339,10 @@ public final class AuthlibInjector {
transformer.units.add(new AuthlibLogInterceptor());
}
transformer.units.add(new MainArgumentsTransformer());
transformer.units.add(new ConstantURLTransformUnit(urlProcessor));
transformer.units.add(new CitizensTransformer());
transformer.units.add(new MC52974Workaround());
transformer.units.add(new LaunchWrapperTransformer());
transformer.units.add(new SkinWhitelistTransformUnit(config.getSkinDomains().toArray(new String[0])));

View file

@ -0,0 +1,71 @@
package moe.yushi.authlibinjector.transform;
import static java.util.stream.Collectors.joining;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.ASM7;
import static org.objectweb.asm.Opcodes.ASTORE;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import java.util.stream.Stream;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import moe.yushi.authlibinjector.util.Logging;
public class MainArgumentsTransformer implements TransformUnit {
private static final List<Function<String[], String[]>> LISTENERS = new CopyOnWriteArrayList<>();
public static String[] processMainArguments(String[] args) {
Logging.TRANSFORM.fine(() -> "Main arguments: " + Stream.of(args).collect(joining(" ")));
String[] result = args;
for (Function<String[], String[]> listener : LISTENERS) {
result = listener.apply(result);
}
return result;
}
public static List<Function<String[], String[]>> getListeners() {
return LISTENERS;
}
@Override
public Optional<ClassVisitor> transform(ClassLoader classLoader, String className, ClassVisitor writer, Runnable modifiedCallback) {
if ("net.minecraft.client.main.Main".equals(className)) {
return Optional.of(new ClassVisitor(ASM7, writer) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
if ("main".equals(name) && "([Ljava/lang/String;)V".equals(descriptor)) {
return new MethodVisitor(ASM7, super.visitMethod(access, name, descriptor, signature, exceptions)) {
@Override
public void visitCode() {
super.visitCode();
modifiedCallback.run();
super.visitVarInsn(ALOAD, 0);
super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(MainArgumentsTransformer.class), "processMainArguments", "([Ljava/lang/String;)[Ljava/lang/String;", false);
super.visitVarInsn(ASTORE, 0);
}
};
} else {
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
}
});
} else {
return Optional.empty();
}
}
@Override
public String toString() {
return "Main Arguments Transformer";
}
}

View file

@ -0,0 +1,106 @@
package moe.yushi.authlibinjector.transform.support;
import static java.util.Collections.unmodifiableSet;
import static org.objectweb.asm.Opcodes.ASM7;
import static org.objectweb.asm.Opcodes.ILOAD;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.ISTORE;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import moe.yushi.authlibinjector.transform.TransformUnit;
import moe.yushi.authlibinjector.util.Logging;
/**
* See <https://github.com/yushijinhun/authlib-injector/issues/30>
*/
public class MC52974Workaround implements TransformUnit {
private static boolean affected = false;
// ==== Detect affected versions ====
public static final Set<String> AFFECTED_VERSION_SERIES = unmodifiableSet(new HashSet<>(Arrays.asList(
"1.7.4", // MC 1.7.9 uses this
"1.7.10",
"1.8",
"1.9",
"1.10",
"1.11",
"1.12")));
public static Optional<String> inferVersionSeries(String[] args) {
boolean hit = false;
for (String arg : args) {
if (hit) {
if (arg.startsWith("--")) {
// arg doesn't seem to be a value
// maybe the previous argument is a value, but we wrongly recognized it as an option
hit = false;
} else {
return Optional.of(arg);
}
}
if ("--assetIndex".equals(arg)) {
hit = true;
}
}
return Optional.empty();
}
public static void acceptMainArguments(String[] args) {
inferVersionSeries(args).ifPresent(assetIndexName -> {
if (AFFECTED_VERSION_SERIES.contains(assetIndexName)) {
Logging.HTTPD.info("Current version series is " + assetIndexName + ", enable MC-52974 workaround.");
affected = true;
}
});
}
// ====
public static boolean overwriteRequireSecure(boolean requireSecure) {
if (affected) {
return true;
}
return requireSecure;
}
@Override
public Optional<ClassVisitor> transform(ClassLoader classLoader, String className, ClassVisitor writer, Runnable modifiedCallback) {
if ("com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService".equals(className)) {
return Optional.of(new ClassVisitor(ASM7, writer) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
if ("fillGameProfile".equals(name) && "(Lcom/mojang/authlib/GameProfile;Z)Lcom/mojang/authlib/GameProfile;".equals(descriptor)) {
return new MethodVisitor(ASM7, super.visitMethod(access, name, descriptor, signature, exceptions)) {
@Override
public void visitCode() {
super.visitCode();
modifiedCallback.run();
super.visitVarInsn(ILOAD, 2);
super.visitMethodInsn(INVOKESTATIC, Type.getInternalName(MC52974Workaround.class), "overwriteRequireSecure", "(Z)Z", false);
super.visitVarInsn(ISTORE, 2);
}
};
} else {
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
}
});
} else {
return Optional.empty();
}
}
@Override
public String toString() {
return "MC-52974 Workaround";
}
}

View file

@ -0,0 +1,89 @@
package moe.yushi.authlibinjector.test;
import static moe.yushi.authlibinjector.transform.support.MC52974Workaround.inferVersionSeries;
import static org.junit.Assert.assertEquals;
import java.util.Optional;
import org.junit.Test;
public class MC52974WorkaroundTest {
@Test
public void testNone() {
assertEquals(inferVersionSeries(new String[] {
""
}), Optional.empty());
}
@Test
public void testHalf1() {
assertEquals(inferVersionSeries(new String[] {
"--assetIndex"
}), Optional.empty());
}
@Test
public void testHalf2() {
assertEquals(inferVersionSeries(new String[] {
"--width",
"854",
"--height",
"480",
"--username",
"character2",
"--version",
"HMCL 3.2.SNAPSHOT",
"--gameDir",
"/home/yushijinhun/.minecraft",
"--assetsDir",
"/home/yushijinhun/.minecraft/assets",
"--assetIndex"
}), Optional.empty());
}
@Test
public void testAmbiguity1() {
assertEquals(inferVersionSeries(new String[] {
"--username",
"--assetIndex"
}), Optional.empty());
}
@Test
public void testAmbiguity2() {
assertEquals(inferVersionSeries(new String[] {
"--demo",
"--assetIndex",
"1.12"
}), Optional.of("1.12"));
}
@Test
public void test1_7_10() {
assertEquals(inferVersionSeries(new String[] {
"--width",
"854",
"--height",
"480",
"--username",
"character2",
"--version",
"HMCL 3.2.SNAPSHOT",
"--gameDir",
"/home/yushijinhun/.minecraft",
"--assetsDir",
"/home/yushijinhun/.minecraft/assets",
"--assetIndex",
"1.7.10",
"--uuid",
"e448fdeff6394b3fac7aecc291446329",
"--accessToken",
"65a7fe601b02439fa90bea52b7d46ab5",
"--userProperties",
"{}",
"--userType",
"mojang"
}), Optional.of("1.7.10"));
}
}