Skip to content

Commit

Permalink
Fix infinite loop in forge if patch parsing fails, fix compat with up…
Browse files Browse the repository at this point in the history
…graded apache-compress
  • Loading branch information
eigenraven committed Jun 30, 2024
1 parent 9d05048 commit 5b22a60
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package me.eigenraven.lwjgl3ify.redirects;

import java.io.EOFException;
import java.io.IOException;
import java.util.jar.JarEntry;

public final class JarInputStream {

public static JarEntry getNextJarEntrySafe(final java.util.jar.JarInputStream jis) throws IOException {
try {
return jis.getNextJarEntry();
} catch (EOFException eof) {
System.err.println("EOF caught while searching for forge patches: " + eof);
eof.printStackTrace(System.err);
return null;
}
}
}
3 changes: 3 additions & 0 deletions src/main/java/me/eigenraven/lwjgl3ify/redirects/Pack200.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,14 @@ public void unpack(InputStream in, JarOutputStream out) throws IOException {
// The Apache library doesn't handle LzmaInputStreams well
final byte[] allData = IOUtils.toByteArray(in);
parent.unpack(new ByteArrayInputStream(allData), out);
out.flush();
out.close(); // Forge expects this
}

@Override
public void unpack(File in, JarOutputStream out) throws IOException {
parent.unpack(in, out);
out.flush();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;

import com.gtnewhorizons.retrofuturabootstrap.api.ClassNodeHandle;
Expand All @@ -33,12 +34,13 @@ public class ForgePatchTransformer implements RfbClassTransformer {
return "forge-patch";
}

public static final String CLASS_PATCH_MANAGER = "cpw.mods.fml.common.patcher.ClassPatchManager";
public static final String TRACING_PRINT_STREAM = "cpw.mods.fml.common.TracingPrintStream";
public static final String FML_SECURITY_MANAGER = "cpw.mods.fml.relauncher.FMLSecurityManager";
public static final String ENUM_HELPER = "net.minecraftforge.common.util.EnumHelper";

public static final String[] PATCHED_CLASSES = new String[] { TRACING_PRINT_STREAM, FML_SECURITY_MANAGER,
ENUM_HELPER };
public static final String[] PATCHED_CLASSES = new String[] { CLASS_PATCH_MANAGER, TRACING_PRINT_STREAM,
FML_SECURITY_MANAGER, ENUM_HELPER };

@Override
public boolean shouldTransformClass(@NotNull ExtensibleClassLoader classLoader,
Expand All @@ -59,12 +61,50 @@ public void transformClass(@NotNull ExtensibleClassLoader classLoader, @NotNull
return;
}
switch (className) {
case CLASS_PATCH_MANAGER -> tfClassPatchManager(classNode);
case TRACING_PRINT_STREAM -> tfTracingPrintStream(classNode);
case FML_SECURITY_MANAGER -> tfFmlSecurityManager(classNode);
case ENUM_HELPER -> tfEnumHelper(classNode);
}
}

private void tfClassPatchManager(@NotNull ClassNodeHandle handle) {
// Fix an infinite loop if an EOFException happens
final ClassNode node = handle.getNode();
if (node == null || node.methods == null) {
logger.error("Class patch manager missing class data");
return;
}
for (final MethodNode mn : node.methods) {
if (!"setup".equals(mn.name)) {
continue;
}
if (mn.instructions == null || mn.instructions.size() == 0) {
logger.error("ClassPatchManager#setup(Side) missing code");
return;
}
for (final AbstractInsnNode insn : mn.instructions) {
if (insn.getOpcode() != INVOKEVIRTUAL) {
continue;
}
if (!(insn instanceof MethodInsnNode minsn)) {
continue;
}
if (!"java/util/jar/JarInputStream".equals(minsn.owner)) {
continue;
}
if (!"getNextJarEntry".equals(minsn.name)) {
continue;
}
// redirect
minsn.setOpcode(INVOKESTATIC);
minsn.owner = "me/eigenraven/lwjgl3ify/redirects/JarInputStream";
minsn.name = "getNextJarEntrySafe";
minsn.desc = "(Ljava/util/jar/JarInputStream;)Ljava/util/jar/JarEntry;";
}
}
}

private void tfTracingPrintStream(@NotNull ClassNodeHandle handle) {
// Add a close() override that does not close the underlying stream
// Pack200 tries to close this stream when loading patches.
Expand Down

0 comments on commit 5b22a60

Please sign in to comment.