Skip to content

Commit 2ca0af7

Browse files
mizhouxdiecui1202
authored andcommitted
fix telnet invoke NPE #2218 (#2273)
* fix issue #2218 * add some unit tests
1 parent 8ae95c9 commit 2ca0af7

File tree

4 files changed

+56
-0
lines changed

4 files changed

+56
-0
lines changed

dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,19 @@ private static boolean isMatch(Class<?>[] types, List<Object> args) {
6060
for (int i = 0; i < types.length; i++) {
6161
Class<?> type = types[i];
6262
Object arg = args.get(i);
63+
64+
if (arg == null) {
65+
// if the type is primitive, the method to invoke will cause NullPointerException definitely
66+
// so we can offer a specified error message to the invoker in advance and avoid unnecessary invoking
67+
if (type.isPrimitive()) {
68+
throw new NullPointerException(String.format(
69+
"The type of No.%d parameter is primitive(%s), but the value passed is null.", i + 1, type.getName()));
70+
}
71+
72+
// if the type is not primitive, we choose to believe what the invoker want is a null value
73+
continue;
74+
}
75+
6376
if (ReflectUtils.isPrimitive(arg.getClass())) {
6477
if (!ReflectUtils.isPrimitive(type)) {
6578
return false;

dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,6 @@ public interface DemoService {
5757

5858
NonSerialized returnNonSerialized();
5959

60+
long add(int a, long b);
61+
6062
}

dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,9 @@ public void nonSerializedParameter(NonSerialized ns) {
103103
public NonSerialized returnNonSerialized() {
104104
return new NonSerialized();
105105
}
106+
107+
public long add(int a, long b) {
108+
return a + b;
109+
}
110+
106111
}

dubbo-rpc/dubbo-rpc-dubbo/src/test/java/com/alibaba/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
import static org.junit.Assert.assertEquals;
3535
import static org.junit.Assert.assertTrue;
36+
import static org.junit.Assert.fail;
3637
import static org.mockito.ArgumentMatchers.any;
3738
import static org.mockito.BDDMockito.given;
3839
import static org.mockito.Mockito.mock;
@@ -68,6 +69,41 @@ public void testInvokeDefaultSService() throws RemotingException {
6869
assertTrue(result.contains("Use default service com.alibaba.dubbo.rpc.protocol.dubbo.support.DemoService.\r\n\"ok\"\r\n"));
6970
}
7071

72+
@SuppressWarnings("unchecked")
73+
@Test
74+
public void testInvokeByPassingNullValue() throws RemotingException {
75+
mockInvoker = mock(Invoker.class);
76+
given(mockInvoker.getInterface()).willReturn(DemoService.class);
77+
given(mockInvoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:20883/demo"));
78+
given(mockInvoker.invoke(any(Invocation.class))).willReturn(new RpcResult("ok"));
79+
mockChannel = mock(Channel.class);
80+
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
81+
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
82+
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20883"));
83+
DubboProtocol.getDubboProtocol().export(mockInvoker);
84+
// pass null value to parameter of primitive type
85+
try {
86+
invoke.telnet(mockChannel, "DemoService.add(null, 2)");
87+
fail("It should cause a NullPointerException by the above code.");
88+
} catch (NullPointerException ex) {
89+
String message = ex.getMessage();
90+
assertEquals("The type of No.1 parameter is primitive(int), but the value passed is null.", message);
91+
}
92+
try {
93+
invoke.telnet(mockChannel, "DemoService.add(1, null)");
94+
fail("It should cause a NullPointerException by the above code.");
95+
} catch (NullPointerException ex) {
96+
String message = ex.getMessage();
97+
assertEquals("The type of No.2 parameter is primitive(long), but the value passed is null.", message);
98+
}
99+
// pass null value to parameter of object type
100+
try {
101+
invoke.telnet(mockChannel, "DemoService.sayHello(null)");
102+
} catch (NullPointerException ex) {
103+
fail("It shouldn't cause a NullPointerException by the above code.");
104+
}
105+
}
106+
71107
@SuppressWarnings("unchecked")
72108
@Test
73109
public void testInvokeAutoFindMethod() throws RemotingException {

0 commit comments

Comments
 (0)