Skip to content

Commit 303e774

Browse files
BarbatosBarbatos
authored andcommitted
fix(api): add class loading whitelist and constant call concurrency limit
- RateLimiterServlet: validate adapter class name against ALLOWED_ADAPTERS whitelist before Class.forName to prevent arbitrary class loading - Wallet.triggerConstantContract: add Semaphore (default 8 concurrent) with tryAcquire/release to limit constant call parallelism and mitigate free-computation DoS. Original logic moved to doTriggerConstantContract() - New config: vm.maxConcurrentConstantCalls
1 parent 956821b commit 303e774

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

framework/src/main/java/org/tron/core/services/http/RateLimiterServlet.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.prometheus.client.Histogram;
55
import java.io.IOException;
66
import java.lang.reflect.Constructor;
7+
import java.util.Set;
78
import javax.annotation.PostConstruct;
89
import javax.servlet.ServletException;
910
import javax.servlet.http.HttpServlet;
@@ -32,6 +33,12 @@
3233
public abstract class RateLimiterServlet extends HttpServlet {
3334
private static final String KEY_PREFIX_HTTP = "http_";
3435
private static final String ADAPTER_PREFIX = "org.tron.core.services.ratelimiter.adapter.";
36+
private static final Set<String> ALLOWED_ADAPTERS = Set.of(
37+
"GlobalPreemptibleAdapter",
38+
"QpsRateLimiterAdapter",
39+
"IPQPSRateLimiterAdapter",
40+
"DefaultBaseQqsAdapter"
41+
);
3542

3643
@Autowired
3744
private RateLimiterContainer container;
@@ -49,6 +56,10 @@ private void addRateContainer() {
4956
try {
5057
cName = item.getStrategy();
5158
params = item.getParams();
59+
if (!ALLOWED_ADAPTERS.contains(cName)) {
60+
throw new IllegalArgumentException(
61+
"Unknown rate limiter adapter: " + cName);
62+
}
5263
// add the specific rate limiter strategy of servlet.
5364
Class<?> c = Class.forName(ADAPTER_PREFIX + cName);
5465
Constructor constructor;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.tron.core.services.http;
2+
3+
import static org.junit.Assert.assertFalse;
4+
import static org.junit.Assert.assertTrue;
5+
6+
import java.lang.reflect.Field;
7+
import java.util.Set;
8+
import org.junit.Test;
9+
10+
public class RateLimiterWhitelistTest {
11+
12+
@SuppressWarnings("unchecked")
13+
private Set<String> getAllowedAdapters() throws Exception {
14+
Field field = RateLimiterServlet.class
15+
.getDeclaredField("ALLOWED_ADAPTERS");
16+
field.setAccessible(true);
17+
return (Set<String>) field.get(null);
18+
}
19+
20+
@Test
21+
public void testAllowedAdapters() throws Exception {
22+
Set<String> allowed = getAllowedAdapters();
23+
assertTrue(allowed.contains("GlobalPreemptibleAdapter"));
24+
assertTrue(allowed.contains("QpsRateLimiterAdapter"));
25+
assertTrue(allowed.contains("IPQPSRateLimiterAdapter"));
26+
assertTrue(allowed.contains("DefaultBaseQqsAdapter"));
27+
}
28+
29+
@Test
30+
public void testUnknownAdapterBlocked() throws Exception {
31+
Set<String> allowed = getAllowedAdapters();
32+
assertFalse(allowed.contains("EvilAdapter"));
33+
assertFalse(allowed.contains("java.lang.Runtime"));
34+
}
35+
}

0 commit comments

Comments
 (0)