C# 中 BitConverter.Int64BitsToDouble 的安全性和稳定性问题

本文关键字:稳定性 问题 安全性 BitConverter Int64BitsToDouble | 更新日期: 2023-09-27 18:30:34

我正在编写一个自定义反序列化系统,用于通过网络打包数据,并通过以下方式序列化双精度:

private static string EncodeDouble(double raw)
{
    long value = BitConverter.DoubleToInt64Bits(raw);
    return EncodeInteger(value);
}

EncodeInteger函数只是将整数转换为标记字符串,以便反序列化代码知道它具有正确的数据类型。

另一方面,我正在反序列化如下:

private static double DecodeDouble(string raw)
{
    long value = DecodeInteger<long>(raw);
    return BitConverter.Int64BitsToDouble(value);
}

同样,DecodeInteger只是删除标记并验证该值是否在 long 范围内,然后强制转换为 long。这是安全的,因为如果出现任何问题,它只会抛出异常。

担心的原因是,在进入参考源后,我看到了这种直接的不安全转换:

public static unsafe double Int64BitsToDouble(long value) {
    return *((double *)&value);
} 

我预见的问题是,长头的值可以任意修改,因为它是通过网络进行的。我不是在担心任意修改值,而是担心如果发送无效的基础double表示形式,CLR 可能会遇到问题。

我不确定是否有任何潜在的long值未映射到有效double,但如果有,我可能会看到什么?CLR 是否会崩溃,从而导致拒绝服务情况?还是有可以抓住的例外?

C# 中 BitConverter.Int64BitsToDouble 的安全性和稳定性问题

AFAIK 这里没有任何"无效"值;只是不是你最初想到的值。所以你,在拒绝服务方面你没有什么可担心的。请注意,相比之下,decimal可以有无效的二进制表示形式 - 这些只会抛出异常,单个调用将失败 - 仍然不是拒绝服务(只是:他们会看到失败)。

不过,就我个人而言,我建议将double编码为long然后编码为string可能是以困难/低效的方式做事。如果你迫切需要它作为string,请考虑对位进行base-64编码。