fix: h2 js classname $$ parse failed
Dev Deploy / Build Jar (ubuntu-latest) (push) Waiting to run
Dev Deploy / Build Jar (windows-latest) (push) Waiting to run
Dev Deploy / Docker Push (push) Blocked by required conditions
Dev Deploy / Deploy to Maven Central (push) Blocked by required conditions
Dev Deploy / Deploy to Northflank (push) Blocked by required conditions
MemShell IntegrationTest / jenkins (push) Waiting to run
MemShell IntegrationTest / xxljob (push) Waiting to run
MemShell IntegrationTest / dubbo (push) Waiting to run
MemShell IntegrationTest / springwebmvc (push) Waiting to run
MemShell IntegrationTest / springwebflux (push) Waiting to run
MemShell IntegrationTest / struts2 (push) Waiting to run
MemShell IntegrationTest / tomcat (push) Waiting to run
MemShell IntegrationTest / glassfish (push) Waiting to run
MemShell IntegrationTest / jbosseap (push) Waiting to run
MemShell IntegrationTest / payara (push) Waiting to run
MemShell IntegrationTest / wildfly (push) Waiting to run
MemShell IntegrationTest / jetty (push) Waiting to run
MemShell IntegrationTest / weblogic (push) Waiting to run
MemShell IntegrationTest / jbossas (push) Waiting to run
MemShell IntegrationTest / resin (push) Waiting to run
MemShell IntegrationTest / geronimo (push) Waiting to run
MemShell IntegrationTest / websphere7 (push) Waiting to run
MemShell IntegrationTest / websphere (push) Waiting to run
Probe IntegrationTest / springwebmvc (push) Waiting to run
Probe IntegrationTest / springwebflux (push) Waiting to run
Probe IntegrationTest / struts2 (push) Waiting to run
Probe IntegrationTest / tomcat (push) Waiting to run
Probe IntegrationTest / glassfish (push) Waiting to run
Probe IntegrationTest / jbosseap (push) Waiting to run
Probe IntegrationTest / payara (push) Waiting to run
Probe IntegrationTest / wildfly (push) Waiting to run
Probe IntegrationTest / jetty (push) Waiting to run
Probe IntegrationTest / jbossas (push) Waiting to run
Probe IntegrationTest / resin (push) Waiting to run
Probe IntegrationTest / weblogic (push) Waiting to run
Probe IntegrationTest / websphere7 (push) Waiting to run
Probe IntegrationTest / websphere (push) Waiting to run
Unit-Test / UniteTest (push) Waiting to run

This commit is contained in:
ReaJason
2026-09-24 12:58:45 +08:00
parent 6bb4a1c2e7
commit 5047ab849f
2 changed files with 65 additions and 5 deletions
@@ -14,6 +14,12 @@ public class H2JSPacker implements Packer {
@Override
public String pack(ClassPackerConfig config) {
String script = Packers.ScriptEngine.getInstance().pack(config);
// H2 的 $$..$$ 美元引用字符串没有转义机制,类名(如 SOAPUtils$Proxy0$$Lambda$1)中的
// $$ 会提前闭合字面量。$$ 只会出现在 JS 的字符串字面量中,拆成 "$"+"$" 拼接即可,
// 既不残留 $$,又能还原出原类名
while (script.contains("$$")) {
script = script.replace("$$", "$\"+\"$");
}
return template.replace("{{script}}", script.replaceAll(";", "\\\\;"));
}
}
@@ -3,6 +3,14 @@ package com.reajason.javaweb.packer.h2;
import com.reajason.javaweb.packer.ClassPackerConfig;
import org.junit.jupiter.api.Test;
import javax.script.Compilable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* @author ReaJason
* @since 2025/6/28
@@ -10,10 +18,56 @@ import org.junit.jupiter.api.Test;
class H2JSPackerTest {
@Test
void test() {
H2JSPacker h2JSPacker = new H2JSPacker();
void pack() throws Exception {
ClassPackerConfig classPackerConfig = new ClassPackerConfig();
classPackerConfig.setClassBytesBase64Str("bebe");
System.out.println(h2JSPacker.pack(classPackerConfig));
classPackerConfig.setClassName("com.reajason.javaweb.ErrorAbcdHandler");
classPackerConfig.setClassBytesBase64Str("aGVsbG8=");
String url = new H2JSPacker().pack(classPackerConfig);
String js = extractJs(url);
assertFalse(js.contains("$$"), "dollar-quoted body should not contain $$: " + js);
compileJs(js);
assertClassName(js, "com.reajason.javaweb.ErrorAbcdHandler");
}
}
@Test
void packClassNameWithLambdaSuffix() throws Exception {
ClassPackerConfig classPackerConfig = new ClassPackerConfig();
classPackerConfig.setClassName("le.gso.SzyHj.SOAPUtils$Proxy0$$Lambda$1");
classPackerConfig.setClassBytesBase64Str("aGVsbG8=");
String url = new H2JSPacker().pack(classPackerConfig);
String js = extractJs(url);
assertFalse(js.contains("$$"), "dollar-quoted body should not contain $$: " + js);
compileJs(js);
assertClassName(js, "le.gso.SzyHj.SOAPUtils$Proxy0$$Lambda$1");
}
/**
* 提取 $$..$$ 美元引用字符串中的 JS 源码,并还原 H2 连接串层面的 \; 转义
*/
private String extractJs(String url) {
String body = url.substring(url.indexOf("$$") + 2, url.lastIndexOf("$$"));
return body.substring("//javascript\n".length()).replace("\\;", ";");
}
/**
* 只解析不执行,验证拼接后的 JS 语法仍然合法
*/
private void compileJs(String js) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
assertNotNull(engine, "need a JDK with Nashorn to run this test");
((Compilable) engine).compile(js);
}
/**
* 只执行 className 赋值语句,验证 $$ 拆分成 "$"+"$" 后仍能还原出原类名
*/
private void assertClassName(String js, String expectedClassName) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
int start = js.indexOf("var className");
if (start < 0) {
throw new AssertionError("className assignment not found in: " + js);
}
engine.eval(js.substring(start, js.indexOf(';', start)));
assertEquals(expectedClassName, engine.get("className"));
}
}