|
1 | 1 | package org.tron.core.services.jsonrpc; |
2 | 2 |
|
| 3 | +import com.fasterxml.jackson.core.JsonFactory; |
3 | 4 | import com.fasterxml.jackson.core.JsonProcessingException; |
| 5 | +import com.fasterxml.jackson.core.StreamReadConstraints; |
4 | 6 | import com.fasterxml.jackson.databind.JsonNode; |
5 | 7 | import com.fasterxml.jackson.databind.ObjectMapper; |
6 | 8 | import com.fasterxml.jackson.databind.node.ArrayNode; |
|
30 | 32 | @Slf4j(topic = "API") |
31 | 33 | public class JsonRpcServlet extends RateLimiterServlet { |
32 | 34 |
|
33 | | - private static final ObjectMapper MAPPER = new ObjectMapper(); |
| 35 | + // Snapshot of node.http.maxNestingDepth / maxTokenCount at class-load time (after Args.setParam). |
| 36 | + private static final ObjectMapper MAPPER = buildMapper(); |
| 37 | + |
| 38 | + private static ObjectMapper buildMapper() { |
| 39 | + CommonParameter p = CommonParameter.getInstance(); |
| 40 | + JsonFactory factory = JsonFactory.builder() |
| 41 | + .streamReadConstraints(StreamReadConstraints.builder() |
| 42 | + .maxNestingDepth(p.getMaxNestingDepth()) |
| 43 | + .maxTokenCount(p.getMaxTokenCount()) |
| 44 | + .build()) |
| 45 | + .build(); |
| 46 | + return new ObjectMapper(factory); |
| 47 | + } |
34 | 48 |
|
35 | 49 | private enum JsonRpcError { |
36 | 50 | PARSE_ERROR(-32700), |
@@ -105,6 +119,11 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I |
105 | 119 | return; |
106 | 120 | } |
107 | 121 |
|
| 122 | + if (!rootNode.isObject() && !rootNode.isArray()) { |
| 123 | + writeJsonRpcError(resp, JsonRpcError.INVALID_REQUEST, "Invalid Request", null, false); |
| 124 | + return; |
| 125 | + } |
| 126 | + |
108 | 127 | boolean isBatch = rootNode.isArray(); |
109 | 128 | if (isBatch && rootNode.isEmpty()) { |
110 | 129 | writeJsonRpcError(resp, JsonRpcError.INVALID_REQUEST, "Invalid Request", null, false); |
@@ -158,6 +177,11 @@ private void handleBatch(HttpServletResponse resp, JsonNode rootNode, int maxRes |
158 | 177 | for (int i = 0; i < rootNode.size(); i++) { |
159 | 178 | JsonNode subRequest = rootNode.get(i); |
160 | 179 |
|
| 180 | + if (!subRequest.isObject()) { |
| 181 | + batchResult.add(buildErrorNode(JsonRpcError.INVALID_REQUEST, "Invalid Request", null)); |
| 182 | + continue; |
| 183 | + } |
| 184 | + |
161 | 185 | if (overflow) { |
162 | 186 | // Notifications (no "id") do not get a response even on overflow. |
163 | 187 | if (subRequest.has("id")) { |
@@ -219,7 +243,7 @@ private void handleBatch(HttpServletResponse resp, JsonNode rootNode, int maxRes |
219 | 243 | } |
220 | 244 |
|
221 | 245 | byte[] finalBytes = MAPPER.writeValueAsBytes(batchResult); |
222 | | - resp.setContentType("application/json-rpc; charset=utf-8"); |
| 246 | + resp.setContentType("application/json-rpc"); |
223 | 247 | resp.setStatus(HttpServletResponse.SC_OK); |
224 | 248 | resp.setContentLength(finalBytes.length); |
225 | 249 | resp.getOutputStream().write(finalBytes); |
@@ -261,7 +285,7 @@ private void writeJsonRpcError(HttpServletResponse resp, JsonRpcError error, Str |
261 | 285 | } else { |
262 | 286 | bytes = MAPPER.writeValueAsBytes(errorObj); |
263 | 287 | } |
264 | | - resp.setContentType("application/json-rpc; charset=utf-8"); |
| 288 | + resp.setContentType("application/json-rpc"); |
265 | 289 | resp.setStatus(HttpServletResponse.SC_OK); |
266 | 290 | resp.setContentLength(bytes.length); |
267 | 291 | resp.getOutputStream().write(bytes); |
|
0 commit comments