dubbo 2.5.3对于java.sql的反序列化BUG

背景

这是我之前提的问题:问题链接

在使用dubbo 2.5.3的时候,定义的接口中有一个方法使用了实体类作为参数,而这个实体类中定义了一个变量为java.sql.Time类型。不妨暂且定义接口如下:

//BusinessDto中有一个属性dealTime 为java.sql.Time类型
String queryBusiness(BusinessDto param);

当消费者调用这个接口的时候,如果param中的dealTime为null,那么在提供者那里接收到的整个param都为null,如果这个属性不为null,那么参数可以正常的传递。

问题原因解析

问题出在反序列化的时候。
dubbo使用的序列化是hession2的,而hession2对于Time类的反序列化的源码如下:


    static class SqlTimeFieldDeserializer extends FieldDeserializer {
    private final Field _field;
    SqlTimeFieldDeserializer(Field field)
    {
      _field = field;
    }
    
    void deserialize(AbstractHessianInput in, Object obj)
      throws IOException
    {
      java.sql.Time value = null;
      try {
        java.util.Date date = (java.util.Date) in.readObject();
        value = new java.sql.Time(date.getTime());
        _field.set(obj, value);
      } catch (Exception e) {
        logDeserializeError(_field, obj, value, e);
      }
    }
  }

这里我们可以清楚地看出来,将in读取到的object转为Date然后调用了getTime方法,那么如果我们的dealTime属性为空,那么调用getTime函数必然会抛异常,也就产生了之后的结果。

补充说明

我找到的源码可以看出,对于 java.sql.Date, java.sql.Timestamp, java.sql.Time的反序列化均有问题存在。

  static class SqlDateFieldDeserializer extends FieldDeserializer {
    private final Field _field;
    SqlDateFieldDeserializer(Field field)
    {
      _field = field;
    }
    
    void deserialize(AbstractHessianInput in, Object obj)
      throws IOException
    {
      java.sql.Date value = null;
      try {
        java.util.Date date = (java.util.Date) in.readObject();
        value = new java.sql.Date(date.getTime());
        _field.set(obj, value);
      } catch (Exception e) {
        logDeserializeError(_field, obj, value, e);
      }
    }
  }
  static class SqlTimestampFieldDeserializer extends FieldDeserializer {
    private final Field _field;
    SqlTimestampFieldDeserializer(Field field)
    {
      _field = field;
    }
    
    void deserialize(AbstractHessianInput in, Object obj)
      throws IOException
    {
      java.sql.Timestamp value = null;
      try {
        java.util.Date date = (java.util.Date) in.readObject();
        value = new java.sql.Timestamp(date.getTime());
        _field.set(obj, value);
      } catch (Exception e) {
        logDeserializeError(_field, obj, value, e);
      }
    }
  }
  static class SqlTimeFieldDeserializer extends FieldDeserializer {
    private final Field _field;
    SqlTimeFieldDeserializer(Field field)
    {
      _field = field;
    }
    
    void deserialize(AbstractHessianInput in, Object obj)
      throws IOException
    {
      java.sql.Time value = null;
      try {
        java.util.Date date = (java.util.Date) in.readObject();
        value = new java.sql.Time(date.getTime());
        _field.set(obj, value);
      } catch (Exception e) {
        logDeserializeError(_field, obj, value, e);
      }
    }
  }

而hessian4 则修复了这个问题,在调用getTime之前做了非空判断,如果为空则把这个属性赋null而不是产生异常。

如果已经开始大规模的使用那么不妨使用别的类型,绕过这三个类型即可避免这个问题。

总结

问题来源于同事随口问的一个小问题,挺感兴趣就一直纠缠了下来,发现问题还是挺严重的,另外借用同事的一句话,不再维护的开源软件真的挺危险。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值