dubbo 2.5.3對於java.sql的反序列化BUG

背景

這是我以前提的問題:問題連接java

在使用dubbo 2.5.3的時候,定義的接口中有一個方法使用了實體類做爲參數,而這個實體類中定義了一個變量爲java.sql.Time類型。不妨暫且定義接口以下:sql

//BusinessDto中有一個屬性dealTime 爲java.sql.Time類型
String queryBusiness(BusinessDto param);

當消費者調用這個接口的時候,若是param中的dealTime爲null,那麼在提供者那裏接收到的整個param都爲null,若是這個屬性不爲null,那麼參數能夠正常的傳遞。segmentfault

問題緣由解析

問題出在反序列化的時候。
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函數必然會拋異常,也就產生了以後的結果。code

補充說明

我找到的源碼能夠看出,對於 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而不是產生異常。get

若是已經開始大規模的使用那麼不妨使用別的類型,繞過這三個類型便可避免這個問題。源碼

總結

問題來源於同事隨口問的一個小問題,挺感興趣就一直糾纏了下來,發現問題仍是挺嚴重的,另外借用同事的一句話,再也不維護的開源軟件真的挺危險。開源軟件

相關文章
相關標籤/搜索