Commit 3340467d961b639381483255b3d01009a21aee66

Authored by Mumfrey
1 parent 00d2ffc1

separating event proxy generation to improve resilience against bad transformers

java/client/com/mumfrey/liteloader/client/api/LiteLoaderCoreAPIClient.java
... ... @@ -22,9 +22,10 @@ import com.mumfrey.liteloader.interfaces.ObjectFactory;
22 22 */
23 23 public class LiteLoaderCoreAPIClient extends LiteLoaderCoreAPI
24 24 {
25   - private static final String PKG_LITELOADER_CLIENT = LiteLoaderCoreAPI.PKG_LITELOADER + ".client";
  25 + private static final String PKG_LITELOADER_CLIENT = LiteLoaderCoreAPI.PKG_LITELOADER + ".client";
26 26  
27 27 private static final String[] requiredTransformers = {
  28 + LiteLoaderCoreAPI.PKG_LITELOADER + ".transformers.event.EventProxyTransformer",
28 29 LiteLoaderCoreAPI.PKG_LITELOADER + ".launch.LiteLoaderTransformer",
29 30 LiteLoaderCoreAPIClient.PKG_LITELOADER_CLIENT + ".transformers.CrashReportTransformer"
30 31 };
... ...
java/common/com/mumfrey/liteloader/launch/RealmsJsonUpdateThread.java
... ... @@ -106,11 +106,7 @@ public class RealmsJsonUpdateThread extends Thread
106 106  
107 107 private boolean writeLocalVersionJson(Map<String, ?> localJson)
108 108 {
109   - File versionDir = new File(this.versionsDir, this.version);
110   - if (!versionDir.exists() || !versionDir.isDirectory()) return false;
111   -
112   - File versionJsonFile = new File(versionDir, this.version + ".json");
113   -
  109 + File versionJsonFile = this.getLocalVersionJsonFile();
114 110 FileWriter writer = null;
115 111  
116 112 try
... ... @@ -227,11 +223,8 @@ public class RealmsJsonUpdateThread extends Thread
227 223 @SuppressWarnings("unchecked")
228 224 private Map<String, ?> getLocalVersionJson()
229 225 {
230   - File versionDir = new File(this.versionsDir, this.version);
231   - if (!versionDir.exists() || !versionDir.isDirectory()) return null;
232   -
233   - File versionJsonFile = new File(versionDir, this.version + ".json");
234   - if (!versionJsonFile.exists()) return null;
  226 + File versionJsonFile = this.getLocalVersionJsonFile();
  227 + if (versionJsonFile == null || !versionJsonFile.exists()) return null;
235 228  
236 229 FileReader reader = null;
237 230  
... ... @@ -254,13 +247,22 @@ public class RealmsJsonUpdateThread extends Thread
254 247  
255 248 private boolean isLocalJsonUpToDate()
256 249 {
257   - File versionDir = new File(this.versionsDir, this.version);
258   - if (!versionDir.exists() || !versionDir.isDirectory()) return false;
259   -
260   - File versionJsonFile = new File(versionDir, this.version + ".json");
261   - if (!versionJsonFile.exists()) return false;
  250 + File versionJsonFile = this.getLocalVersionJsonFile();
  251 + if (versionJsonFile == null || !versionJsonFile.exists()) return false;
262 252  
263 253 long deltaTime = System.currentTimeMillis() - versionJsonFile.lastModified();
264 254 return deltaTime < 86400000;
265 255 }
  256 +
  257 + /**
  258 + * @return
  259 + */
  260 + private File getLocalVersionJsonFile()
  261 + {
  262 + File versionDir = new File(this.versionsDir, this.version);
  263 + if (!versionDir.exists() || !versionDir.isDirectory()) return null;
  264 +
  265 + File versionJsonFile = new File(versionDir, this.version + ".json");
  266 + return versionJsonFile;
  267 + }
266 268 }
... ...
java/common/com/mumfrey/liteloader/transformers/event/EventInjectionTransformer.java
... ... @@ -10,14 +10,11 @@ import java.util.Set;
10 10 import java.util.TreeSet;
11 11  
12 12 import org.objectweb.asm.ClassWriter;
13   -import org.objectweb.asm.Opcodes;
14 13 import org.objectweb.asm.tree.AbstractInsnNode;
15 14 import org.objectweb.asm.tree.ClassNode;
16   -import org.objectweb.asm.tree.InsnNode;
17 15 import org.objectweb.asm.tree.MethodNode;
18 16 import org.objectweb.asm.util.CheckClassAdapter;
19 17  
20   -import com.mumfrey.liteloader.core.runtime.Obf;
21 18 import com.mumfrey.liteloader.transformers.ClassTransformer;
22 19 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
23 20  
... ... @@ -59,7 +56,7 @@ public abstract class EventInjectionTransformer extends ClassTransformer
59 56 /**
60 57 * Multiple event injection transformers may exist but to allow co-operation the events themselves are registered
61 58 * statically. The first EventInjectionTransformer instance to be created becomes the "master" and is actually responsible
62   - * for injecting the events and transforming the EventProxy class.
  59 + * for injecting the events
63 60 */
64 61 private static EventInjectionTransformer master;
65 62  
... ... @@ -156,23 +153,6 @@ public abstract class EventInjectionTransformer extends ClassTransformer
156 153 {
157 154 if (EventInjectionTransformer.master == this)
158 155 {
159   - if (transformedName != null && transformedName.startsWith(Obf.EventProxy.name))
160   - {
161   - int dollarPos = transformedName.indexOf('$');
162   - int proxyIndex = (dollarPos > -1) ? Integer.parseInt(transformedName.substring(dollarPos + 1)) : 0;
163   - if (proxyIndex != 1)
164   - {
165   - try
166   - {
167   - return this.transformEventProxy(transformedName, basicClass, proxyIndex);
168   - }
169   - catch (Throwable th)
170   - {
171   - th.printStackTrace();
172   - }
173   - }
174   - }
175   -
176 156 if (basicClass != null && EventInjectionTransformer.eventMappings.containsKey(transformedName))
177 157 {
178 158 return this.injectEvents(basicClass, EventInjectionTransformer.eventMappings.get(transformedName));
... ... @@ -182,36 +162,6 @@ public abstract class EventInjectionTransformer extends ClassTransformer
182 162 return basicClass;
183 163 }
184 164  
185   - private byte[] transformEventProxy(String transformedName, byte[] basicClass, int proxyIndex)
186   - {
187   - ClassNode classNode = this.getProxyByteCode(transformedName, basicClass, proxyIndex);
188   - return this.writeClass(Event.populateProxy(classNode, proxyIndex == 0 ? 1 : proxyIndex));
189   - }
190   -
191   - private ClassNode getProxyByteCode(String transformedName, byte[] basicClass, int proxyIndex)
192   - {
193   - if (proxyIndex == 0 || basicClass != null)
194   - {
195   - ClassNode classNode = this.readClass(basicClass, true);
196   -
197   - for (MethodNode method : classNode.methods)
198   - {
199   - // Strip the sanity code out of the EventProxy class initialiser
200   - if ("<clinit>".equals(method.name))
201   - {
202   - method.instructions.clear();
203   - method.instructions.add(new InsnNode(Opcodes.RETURN));
204   - }
205   - }
206   -
207   - return classNode;
208   - }
209   -
210   - ClassNode classNode = new ClassNode();
211   - classNode.visit(50, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, transformedName.replace('.', '/'), null, "java/lang/Object", null);
212   - return classNode;
213   - }
214   -
215 165 private byte[] injectEvents(byte[] basicClass, Map<String, Map<Event, InjectionPoint>> mappings)
216 166 {
217 167 if (mappings == null) return basicClass;
... ...
java/common/com/mumfrey/liteloader/transformers/event/EventProxyTransformer.java 0 → 100644
  1 +package com.mumfrey.liteloader.transformers.event;
  2 +
  3 +import org.objectweb.asm.Opcodes;
  4 +import org.objectweb.asm.tree.ClassNode;
  5 +import org.objectweb.asm.tree.InsnNode;
  6 +import org.objectweb.asm.tree.MethodNode;
  7 +
  8 +import com.mumfrey.liteloader.core.runtime.Obf;
  9 +import com.mumfrey.liteloader.transformers.ClassTransformer;
  10 +
  11 +/**
  12 + * Transformer responsible for transforming/generating the EventProxy inner classes, separated from the Event Transformer
  13 + * itself so that we can place it higher up the tranformer chain to avoid broken mod transformers screwing things up.
  14 + *
  15 + * @author Adam Mummery-Smith
  16 + */
  17 +public class EventProxyTransformer extends ClassTransformer
  18 +{
  19 + public EventProxyTransformer()
  20 + {
  21 + }
  22 +
  23 + @Override
  24 + public byte[] transform(String name, String transformedName, byte[] basicClass)
  25 + {
  26 + if (transformedName != null && transformedName.startsWith(Obf.EventProxy.name))
  27 + {
  28 + int dollarPos = transformedName.indexOf('$');
  29 + int proxyIndex = (dollarPos > -1) ? Integer.parseInt(transformedName.substring(dollarPos + 1)) : 0;
  30 + if (proxyIndex != 1)
  31 + {
  32 + try
  33 + {
  34 + return this.transformEventProxy(transformedName, basicClass, proxyIndex);
  35 + }
  36 + catch (Throwable th)
  37 + {
  38 + th.printStackTrace();
  39 + }
  40 + }
  41 + }
  42 +
  43 + return basicClass;
  44 + }
  45 +
  46 + private byte[] transformEventProxy(String transformedName, byte[] basicClass, int proxyIndex)
  47 + {
  48 + ClassNode classNode = this.getProxyByteCode(transformedName, basicClass, proxyIndex);
  49 + return this.writeClass(Event.populateProxy(classNode, proxyIndex == 0 ? 1 : proxyIndex));
  50 + }
  51 +
  52 + private ClassNode getProxyByteCode(String transformedName, byte[] basicClass, int proxyIndex)
  53 + {
  54 + if (proxyIndex == 0 || basicClass != null)
  55 + {
  56 + ClassNode classNode = this.readClass(basicClass, true);
  57 +
  58 + for (MethodNode method : classNode.methods)
  59 + {
  60 + // Strip the sanity code out of the EventProxy class initialiser
  61 + if ("<clinit>".equals(method.name))
  62 + {
  63 + method.instructions.clear();
  64 + method.instructions.add(new InsnNode(Opcodes.RETURN));
  65 + }
  66 + }
  67 +
  68 + return classNode;
  69 + }
  70 +
  71 + ClassNode classNode = new ClassNode();
  72 + classNode.visit(50, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, transformedName.replace('.', '/'), null, "java/lang/Object", null);
  73 + return classNode;
  74 + }
  75 +}
... ...