This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/master by this push:
     new b32e604  fix #7201 The client-side and server-side payload parameters 
are inconsistent, and the server-side response data packet length exceeds the 
client-side payload. (#7287)
b32e604 is described below

commit b32e604da57b972c82df580746cc6b54473df2ae
Author: xiaoheng1 <[email protected]>
AuthorDate: Fri Apr 2 10:52:27 2021 +0800

    fix #7201 The client-side and server-side payload parameters are 
inconsistent, and the server-side response data packet length exceeds the 
client-side payload. (#7287)
---
 .../remoting/exchange/codec/ExchangeCodec.java     | 31 +++++++++++++++++++++-
 .../dubbo/remoting/transport/AbstractCodec.java    | 21 ++++++++++++---
 .../rpc/protocol/dubbo/DubboProtocolTest.java      | 18 +++++++++++++
 .../rpc/protocol/dubbo/support/DemoService.java    |  2 ++
 .../protocol/dubbo/support/DemoServiceImpl.java    |  8 ++++++
 5 files changed, 75 insertions(+), 5 deletions(-)

diff --git 
a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java
 
b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java
index 5031470..877f2ca 100644
--- 
a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java
+++ 
b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java
@@ -110,6 +110,14 @@ public class ExchangeCodec extends TelnetCodec {
 
         // get data length.
         int len = Bytes.bytes2int(header, 12);
+
+        // When receiving response, how to exceed the length, then directly 
construct a response to the client.
+        // see more detail from https://github.com/apache/dubbo/issues/7021.
+        Object obj = finishRespWhenOverPayload(channel, len, header);
+        if (null != obj) {
+            return obj;
+        }
+
         checkPayload(channel, len);
 
         int tt = len + HEADER_LENGTH;
@@ -474,5 +482,26 @@ public class ExchangeCodec extends TelnetCodec {
         encodeResponseData(out, data);
     }
 
-
+    private Object finishRespWhenOverPayload(Channel channel, long size, 
byte[] header) {
+        int payload = getPayload(channel);
+        boolean overPayload = isOverPayload(payload, size);
+        if (overPayload) {
+            long reqId = Bytes.bytes2long(header, 4);
+            byte flag = header[2];
+            if ((flag & FLAG_REQUEST) == 0) {
+                Response res = new Response(reqId);
+                if ((flag & FLAG_EVENT) != 0) {
+                    res.setEvent(true);
+                }
+                // get status.
+                byte status = header[3];
+                res.setStatus(Response.CLIENT_ERROR);
+                String errorMsg = "Data length too large: " + size + ", max 
payload: " + payload + ", channel: " + channel;
+                logger.error(errorMsg);
+                res.setErrorMessage(errorMsg);
+                return res;
+            }
+        }
+        return null;
+    }
 }
diff --git 
a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractCodec.java
 
b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractCodec.java
index e84c28e..fd18ed6 100644
--- 
a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractCodec.java
+++ 
b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractCodec.java
@@ -44,16 +44,29 @@ public abstract class AbstractCodec implements Codec2 {
     private static final String SERVER_SIDE = "server";
 
     protected static void checkPayload(Channel channel, long size) throws 
IOException {
+        int payload = getPayload(channel);
+        boolean overPayload = isOverPayload(payload, size);
+        if (overPayload) {
+            ExceedPayloadLimitException e = new ExceedPayloadLimitException(
+                    "Data length too large: " + size + ", max payload: " + 
payload + ", channel: " + channel);
+            logger.error(e);
+            throw e;
+        }
+    }
+
+    protected static int getPayload(Channel channel) {
         int payload = Constants.DEFAULT_PAYLOAD;
         if (channel != null && channel.getUrl() != null) {
             payload = channel.getUrl().getParameter(Constants.PAYLOAD_KEY, 
Constants.DEFAULT_PAYLOAD);
         }
+        return payload;
+    }
+
+    protected static boolean isOverPayload(int payload, long size) {
         if (payload > 0 && size > payload) {
-            ExceedPayloadLimitException e = new ExceedPayloadLimitException(
-                    "Data length too large: " + size + ", max payload: " + 
payload + ", channel: " + channel);
-            logger.error(e);
-            throw e;
+            return true;
         }
+        return false;
     }
 
     protected Serialization getSerialization(Channel channel, Request req) {
diff --git 
a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java
 
b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java
index b1eeff9..3377eeb 100644
--- 
a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java
+++ 
b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java
@@ -231,4 +231,22 @@ public class DubboProtocolTest {
         service = proxy.getProxy(protocol.refer(DemoService.class, url));
         assertEquals(service.getRemoteApplicationName(), "consumer");
     }
+
+    @Test
+    public void testPayloadOverException() throws Exception {
+        DemoService service = new DemoServiceImpl();
+        int port = NetUtils.getAvailablePort();
+        protocol.export(proxy.getInvoker(service, DemoService.class,
+                URL.valueOf("dubbo://127.0.0.1:" + port + "/" + 
DemoService.class.getName()).addParameter("payload", 10 * 1024)));
+        service = proxy.getProxy(protocol.refer(DemoService.class,
+                URL.valueOf("dubbo://127.0.0.1:" + port + "/" + 
DemoService.class.getName()).addParameter("timeout",
+                        6000L).addParameter("payload", 160)));
+        try {
+            service.download(300);
+            Assertions.fail();
+        } catch (Exception expected) {
+            Assertions.assertTrue(expected.getMessage().contains("Data length 
too large"));
+        }
+
+    }
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java
 
b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java
index 40ca4fb..fea53d6 100644
--- 
a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java
+++ 
b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java
@@ -66,4 +66,6 @@ public interface DemoService {
     String getPerson(Man man);
 
     String getRemoteApplicationName();
+
+    byte[] download(int size);
 }
\ No newline at end of file
diff --git 
a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java
 
b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java
index 0d56e3e..ec1d8c6 100644
--- 
a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java
+++ 
b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.rpc.protocol.dubbo.support;
 
 import org.apache.dubbo.rpc.RpcContext;
 
+import java.util.Arrays;
 import java.util.Map;
 import java.util.Set;
 
@@ -126,4 +127,11 @@ public class DemoServiceImpl implements DemoService {
     public String getRemoteApplicationName() {
         return RpcContext.getContext().getRemoteApplicationName();
     }
+
+    @Override
+    public byte[] download(int size) {
+        byte[] bytes = new byte[size];
+        Arrays.fill(bytes, (byte) 0);
+        return bytes;
+    }
 }
\ No newline at end of file

Reply via email to