Skip to content

Commit cec32e7

Browse files
authored
Merge pull request #8 from Sunny6889/fix_risk_biginteger_etc
fix(jsonrpc): add blockNumOrHash length check
2 parents bbf3369 + 090d072 commit cec32e7

9 files changed

Lines changed: 326 additions & 37 deletions

File tree

chainbase/src/main/java/org/tron/core/db2/core/Chainbase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public enum Cursor {
3535
//true:fullnode, false:soliditynode
3636
private ThreadLocal<Cursor> cursor = new ThreadLocal<>();
3737
private ThreadLocal<Long> offset = new ThreadLocal<>();
38-
private Snapshot head;
38+
private volatile Snapshot head;
3939

4040
public Chainbase(Snapshot head) {
4141
this.head = head;

common/src/main/java/org/tron/common/parameter/CommonParameter.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public class CommonParameter {
2525

2626
protected static CommonParameter PARAMETER = new CommonParameter();
2727

28+
// Default QPS values for rate limiters
29+
public static final int DEFAULT_RATE_LIMITER_GLOBAL_QPS = 1000;
30+
public static final int DEFAULT_RATE_LIMITER_GLOBAL_IP_QPS = 1000;
31+
public static final int DEFAULT_RATE_LIMITER_GLOBAL_API_QPS = 1000;
32+
2833
// Runtime chain state: set by VMConfig.initVmHardFork()
2934
// when the energy-limit governance proposal is activated.
3035
// Legacy: should belong to VMConfig, not here.
@@ -373,12 +378,12 @@ public class CommonParameter {
373378
public RateLimiterInitialization rateLimiterInitialization;
374379
@Getter
375380
@Setter
376-
public int rateLimiterGlobalQps = 50000; // from clearParam(), consistent with mainnet.conf
381+
public int rateLimiterGlobalQps = DEFAULT_RATE_LIMITER_GLOBAL_QPS; // from clearParam(), consistent with mainnet.conf
377382
@Getter
378383
@Setter
379-
public int rateLimiterGlobalIpQps = 10000; // from clearParam(), consistent with mainnet.conf
384+
public int rateLimiterGlobalIpQps = DEFAULT_RATE_LIMITER_GLOBAL_IP_QPS; // from clearParam(), consistent with mainnet.conf
380385
@Getter
381-
public int rateLimiterGlobalApiQps = 1000; // from clearParam(), consistent with mainnet.conf
386+
public int rateLimiterGlobalApiQps = DEFAULT_RATE_LIMITER_GLOBAL_API_QPS; // from clearParam(), consistent with mainnet.conf
382387
@Getter
383388
@Setter
384389
public double rateLimiterSyncBlockChain; // clearParam: 3.0

common/src/main/java/org/tron/common/utils/ByteArray.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ public static BigInteger hexToBigInteger(String input) {
152152
}
153153

154154
public static long jsonHexToLong(String x) throws JsonRpcInvalidParamsException {
155+
// Constants for input length validation to prevent DDoS attacks
156+
int MAX_HEX_LONG_LENGTH = 20; // For 64-bit long values (18 chars for 0x7FFFFFFFFFFFFFFF) + safety buffer
157+
if (x == null || x.length() > MAX_HEX_LONG_LENGTH) {
158+
throw new JsonRpcInvalidParamsException("Input cannot be null or too long");
159+
}
160+
155161
if (!x.startsWith("0x")) {
156162
throw new JsonRpcInvalidParamsException("Incorrect hex syntax");
157163
}
@@ -160,6 +166,12 @@ public static long jsonHexToLong(String x) throws JsonRpcInvalidParamsException
160166
}
161167

162168
public static int jsonHexToInt(String x) throws Exception {
169+
// Constants for input length validation to prevent DDoS attacks
170+
int MAX_HEX_INT_LENGTH = 12; // For 32-bit int values (10 chars for 0x7FFFFFFF) + safety buffer
171+
if (x == null || x.length() > MAX_HEX_INT_LENGTH) {
172+
throw new Exception("Incorrect string length");
173+
}
174+
163175
if (!x.startsWith("0x")) {
164176
throw new Exception("Incorrect hex syntax");
165177
}

framework/src/main/java/org/tron/core/config/args/Args.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ public class Args extends CommonParameter {
100100
private static final ConcurrentHashMap<Long, BlockingQueue<ContractEventTrigger>>
101101
solidityContractEventTriggerMap = new ConcurrentHashMap<>();
102102

103-
104103
/**
105104
* set parameters.
106105
*/
@@ -711,15 +710,15 @@ public static void applyConfigParams(
711710

712711
PARAMETER.rateLimiterGlobalQps =
713712
config.hasPath(ConfigKey.RATE_LIMITER_GLOBAL_QPS) ? config
714-
.getInt(ConfigKey.RATE_LIMITER_GLOBAL_QPS) : 50000;
713+
.getInt(ConfigKey.RATE_LIMITER_GLOBAL_QPS) : DEFAULT_RATE_LIMITER_GLOBAL_QPS;
715714

716715
PARAMETER.rateLimiterGlobalIpQps =
717716
config.hasPath(ConfigKey.RATE_LIMITER_GLOBAL_IP_QPS) ? config
718-
.getInt(ConfigKey.RATE_LIMITER_GLOBAL_IP_QPS) : 10000;
717+
.getInt(ConfigKey.RATE_LIMITER_GLOBAL_IP_QPS) : DEFAULT_RATE_LIMITER_GLOBAL_IP_QPS;
719718

720719
PARAMETER.rateLimiterGlobalApiQps =
721720
config.hasPath(ConfigKey.RATE_LIMITER_GLOBAL_API_QPS) ? config
722-
.getInt(ConfigKey.RATE_LIMITER_GLOBAL_API_QPS) : 1000;
721+
.getInt(ConfigKey.RATE_LIMITER_GLOBAL_API_QPS) : DEFAULT_RATE_LIMITER_GLOBAL_API_QPS;
723722

724723
PARAMETER.rateLimiterInitialization = getRateLimiterFromConfig(config);
725724

framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcApiUtil.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@
5656

5757
@Slf4j(topic = "API")
5858
public class JsonRpcApiUtil {
59+
/**
60+
* Maximum allowed length for block identifiers to prevent DDoS attacks.
61+
* Supports block hashes (66 chars) + safety buffer.
62+
*/
63+
private static final int MAX_BLOCK_IDENTIFIER_LENGTH = 128;
5964

6065
public static byte[] convertToTronAddress(byte[] address) {
6166
byte[] newAddress = new byte[21];
@@ -85,6 +90,13 @@ public static String getMethodSign(String method) {
8590
return Hex.toHexString(selector);
8691
}
8792

93+
public static void validateBlockNumOrHashOrTag(String input)
94+
throws JsonRpcInvalidParamsException {
95+
if (input == null || input.length() > MAX_BLOCK_IDENTIFIER_LENGTH) {
96+
throw new JsonRpcInvalidParamsException("input is null or length exceeds maximum allowed");
97+
}
98+
}
99+
88100
public static TriggerSmartContract triggerCallContract(byte[] address, byte[] contractAddress,
89101
long callValue, byte[] data, long tokenValue, String tokenId) {
90102
TriggerSmartContract.Builder builder = TriggerSmartContract.newBuilder();

framework/src/main/java/org/tron/core/services/jsonrpc/TronJsonRpcImpl.java

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static org.tron.core.services.jsonrpc.JsonRpcApiUtil.getTransactionIndex;
1010
import static org.tron.core.services.jsonrpc.JsonRpcApiUtil.getTxID;
1111
import static org.tron.core.services.jsonrpc.JsonRpcApiUtil.triggerCallContract;
12+
import static org.tron.core.services.jsonrpc.JsonRpcApiUtil.validateBlockNumOrHashOrTag;
1213

1314
import com.alibaba.fastjson.JSON;
1415
import com.google.common.cache.Cache;
@@ -296,6 +297,7 @@ public String web3Sha3(String data) throws JsonRpcInvalidParamsException {
296297
@Override
297298
public String ethGetBlockTransactionCountByHash(String blockHash)
298299
throws JsonRpcInvalidParamsException {
300+
validateBlockNumOrHashOrTag(blockHash);
299301
Block b = getBlockByJsonHash(blockHash);
300302
if (b == null) {
301303
return null;
@@ -308,6 +310,7 @@ public String ethGetBlockTransactionCountByHash(String blockHash)
308310
@Override
309311
public String ethGetBlockTransactionCountByNumber(String blockNumOrTag)
310312
throws JsonRpcInvalidParamsException {
313+
validateBlockNumOrHashOrTag(blockNumOrTag);
311314
List<Transaction> list = wallet.getTransactionsByJsonBlockId(blockNumOrTag);
312315
if (list == null) {
313316
return null;
@@ -327,6 +330,7 @@ public BlockResult ethGetBlockByHash(String blockHash, Boolean fullTransactionOb
327330
@Override
328331
public BlockResult ethGetBlockByNumber(String blockNumOrTag, Boolean fullTransactionObjects)
329332
throws JsonRpcInvalidParamsException {
333+
validateBlockNumOrHashOrTag(blockNumOrTag);
330334
final Block b = wallet.getByJsonBlockId(blockNumOrTag);
331335
return (b == null ? null : getBlockResult(b, fullTransactionObjects));
332336
}
@@ -393,6 +397,9 @@ public String getLatestBlockNum() {
393397
@Override
394398
public String getTrxBalance(String address, String blockNumOrTag)
395399
throws JsonRpcInvalidParamsException {
400+
// Add length check and validate hex format to prevent DDoS attacks
401+
validateBlockNumOrHashOrTag(blockNumOrTag);
402+
396403
if (EARLIEST_STR.equalsIgnoreCase(blockNumOrTag)
397404
|| PENDING_STR.equalsIgnoreCase(blockNumOrTag)
398405
|| FINALIZED_STR.equalsIgnoreCase(blockNumOrTag)) {
@@ -409,12 +416,6 @@ public String getTrxBalance(String address, String blockNumOrTag)
409416
}
410417
return ByteArray.toJsonHex(balance);
411418
} else {
412-
try {
413-
ByteArray.hexToBigInteger(blockNumOrTag);
414-
} catch (Exception e) {
415-
throw new JsonRpcInvalidParamsException(BLOCK_NUM_ERROR);
416-
}
417-
418419
throw new JsonRpcInvalidParamsException(QUANTITY_NOT_SUPPORT_ERROR);
419420
}
420421
}
@@ -535,6 +536,7 @@ private String call(byte[] ownerAddressByte, byte[] contractAddressByte, long va
535536
@Override
536537
public String getStorageAt(String address, String storageIdx, String blockNumOrTag)
537538
throws JsonRpcInvalidParamsException {
539+
validateBlockNumOrHashOrTag(blockNumOrTag);
538540
if (EARLIEST_STR.equalsIgnoreCase(blockNumOrTag)
539541
|| PENDING_STR.equalsIgnoreCase(blockNumOrTag)
540542
|| FINALIZED_STR.equalsIgnoreCase(blockNumOrTag)) {
@@ -558,19 +560,14 @@ public String getStorageAt(String address, String storageIdx, String blockNumOrT
558560
DataWord value = storage.getValue(new DataWord(ByteArray.fromHexString(storageIdx)));
559561
return ByteArray.toJsonHex(value == null ? new byte[32] : value.getData());
560562
} else {
561-
try {
562-
ByteArray.hexToBigInteger(blockNumOrTag);
563-
} catch (Exception e) {
564-
throw new JsonRpcInvalidParamsException(BLOCK_NUM_ERROR);
565-
}
566-
567563
throw new JsonRpcInvalidParamsException(QUANTITY_NOT_SUPPORT_ERROR);
568564
}
569565
}
570566

571567
@Override
572568
public String getABIOfSmartContract(String contractAddress, String blockNumOrTag)
573569
throws JsonRpcInvalidParamsException {
570+
validateBlockNumOrHashOrTag(blockNumOrTag);
574571
if (EARLIEST_STR.equalsIgnoreCase(blockNumOrTag)
575572
|| PENDING_STR.equalsIgnoreCase(blockNumOrTag)
576573
|| FINALIZED_STR.equalsIgnoreCase(blockNumOrTag)) {
@@ -589,12 +586,6 @@ public String getABIOfSmartContract(String contractAddress, String blockNumOrTag
589586
}
590587

591588
} else {
592-
try {
593-
ByteArray.hexToBigInteger(blockNumOrTag);
594-
} catch (Exception e) {
595-
throw new JsonRpcInvalidParamsException(BLOCK_NUM_ERROR);
596-
}
597-
598589
throw new JsonRpcInvalidParamsException(QUANTITY_NOT_SUPPORT_ERROR);
599590
}
600591
}
@@ -791,6 +782,7 @@ private TransactionResult getTransactionByBlockAndIndex(Block block, String inde
791782
@Override
792783
public TransactionResult getTransactionByBlockHashAndIndex(String blockHash, String index)
793784
throws JsonRpcInvalidParamsException {
785+
validateBlockNumOrHashOrTag(blockHash);
794786
final Block block = getBlockByJsonHash(blockHash);
795787

796788
if (block == null) {
@@ -803,6 +795,9 @@ public TransactionResult getTransactionByBlockHashAndIndex(String blockHash, Str
803795
@Override
804796
public TransactionResult getTransactionByBlockNumberAndIndex(String blockNumOrTag, String index)
805797
throws JsonRpcInvalidParamsException {
798+
// Add length check and validate hex format to prevent DDoS attacks
799+
validateBlockNumOrHashOrTag(blockNumOrTag);
800+
806801
Block block = wallet.getByJsonBlockId(blockNumOrTag);
807802
if (block == null) {
808803
return null;
@@ -888,6 +883,8 @@ private TransactionContext findTransactionContext(TransactionInfoList infoList,
888883
@Override
889884
public List<TransactionReceipt> getBlockReceipts(String blockNumOrHashOrTag)
890885
throws JsonRpcInvalidParamsException, JsonRpcInternalException {
886+
// Add length check and validate hex format to prevent DDoS attacks
887+
validateBlockNumOrHashOrTag(blockNumOrHashOrTag);
891888

892889
Block block = null;
893890

@@ -973,6 +970,8 @@ public String getCall(CallArguments transactionCall, Object blockParamObj)
973970

974971
long blockNumber;
975972
try {
973+
// Add length check to prevent DDoS attacks
974+
validateBlockNumOrHashOrTag(blockNumOrTag);
976975
blockNumber = ByteArray.hexToBigInteger(blockNumOrTag).longValue();
977976
} catch (Exception e) {
978977
throw new JsonRpcInvalidParamsException(BLOCK_NUM_ERROR);
@@ -1014,12 +1013,6 @@ public String getCall(CallArguments transactionCall, Object blockParamObj)
10141013
return call(addressData, contractAddressData, transactionCall.parseValue(),
10151014
ByteArray.fromHexString(transactionCall.getData()));
10161015
} else {
1017-
try {
1018-
ByteArray.hexToBigInteger(blockNumOrTag);
1019-
} catch (Exception e) {
1020-
throw new JsonRpcInvalidParamsException(BLOCK_NUM_ERROR);
1021-
}
1022-
10231016
throw new JsonRpcInvalidParamsException(QUANTITY_NOT_SUPPORT_ERROR);
10241017
}
10251018
}

framework/src/main/resources/config.conf

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -442,10 +442,10 @@ rate.limiter = {
442442
# disconnect = 1.0
443443
}
444444

445-
# global qps, default 50000
446-
global.qps = 50000
447-
# IP-based global qps, default 10000
448-
global.ip.qps = 10000
445+
# global qps, default 1000
446+
global.qps = 1000
447+
# IP-based global qps, default 1000
448+
global.ip.qps = 1000
449449
}
450450

451451

0 commit comments

Comments
 (0)