修正Firebird Net Provider 1.7“偏移和长度已超出数组界限”BUG(提供下载)

 

        在笔者的《 修正Firebird Net Provider 1.7中文路径BUG(提供下载)》一文中,笔者基于从Firebird官方网站下载的最新源码,修正了Firebird Net Provider 1.7连接嵌入式版本的中文路径BUG,但最近在将系统切换到Server版本时,却遇到了“偏移和长度已超出数组界限”的错误。如下:

 

修正Firebird Net Provider 1.7“偏移和长度已超出数组界限”BUG(提供下载)_第1张图片
仔细分析“堆栈跟踪”详细信息,发现.NET调用调试信息最上两行已经提示了异常发生的位置,如下:
 

System.Buffer.BlockCopy(Array src, Int32 srcOffset, Array dst, Int32 dstOffset, Int32 count) +0
FirebirdSql.Data.Gds.GdsDatabase.DatabaseInfo(Byte[] items, Byte[] buffer, Int32 bufferLength) +176

 
从该信息中我们可以看出,是FirebirdSql.Data.Gds.GdsDatabase.DatabaseInfo函数调用System.Buffer.BlockCopy时发生了越界异常。
那我们打开FirebirdSql.Data.Gds.GdsDatabase的源文件,找到DatabaseInfo函数的实现部分:

private void DatabaseInfo(byte[] items, byte[] buffer, int bufferLength)
{
       lock (this)
       {
              try
              {
                     // see src/remote/protocol.h for packet definition (p_info struct)             
                     this.Send.Write(IscCodes.op_info_database);      //     operation
                     this.Send.Write(this.handle);                       //     db_handle
                     this.Send.Write(0);                                           //     incarnation
                     this.Send.WriteBuffer(items, items.Length); //     items
                     this.Send.Write(bufferLength);                           //     result buffer length
                     this.Send.Flush();
                     GdsResponse r = this.ReadGenericResponse();
                     Buffer.BlockCopy(r.Data, 0, buffer, 0, bufferLength); // 此行抛出了异常
              }
              catch (IOException)
              {
                     throw new IscException(IscCodes.isc_network_error);
              }
       }
}

 
那我们来看看抛出异常的这行代码,Buffer.BlockCopy函数,是.NET环境提供的平台函数,其参数说明如下:
public static void BlockCopy(
   Array src, //源缓冲区。
   int srcOffset, //src 的字节偏移量。
   Array dst, //目标缓冲区。
   int dstOffset, //dst 的字节偏移量。
   int count//要复制的字节数。
);
根据异常提示,我们可以初步断定,是count参数的值超过了源缓冲区的数组长度,那么,我们很容易就能找出原因:bufferLength超出了r.Data的长度,那既然参数中两个偏移量都是0,那么我们可以使用r.Data.Length来代替bufferLength,以避免bufferLength与r.Data长度不匹配的问题。
即,将此语句更改为Buffer.BlockCopy(r.Data, 0, buffer, 0, r.Data.Length);
修改完毕,编译执行,问题顺利解决。
注意:升级该dll时,请删除系统assambly目录中的FirebirdSql.Data.Firebird全局库。
该修正版本可以到这里下载:
 
 
 
 

你可能感兴趣的:(.net,嵌入式)