【问题标题】:Security and stability issues around BitConverter.Int64BitsToDouble in C#C# 中围绕 BitConverter.Int64BitsToDouble 的安全性和稳定性问题
【发布时间】:2013-09-07 12:36:53
【问题描述】:

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

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);
} 

我预见的问题是long的可以任意修改,因为它是通过网络进行的。我并不担心值被任意修改,而是如果发送无效的底层double 表示,CLR 可能会遇到问题。

我不确定是否有任何潜在的long 映射到有效的double,但如果有,我可能会看到什么? CLR 会崩溃,导致拒绝服务吗?还是有可以被捕获的异常?

【问题讨论】:

    标签: c# security serialization bitconverter


    【解决方案1】:

    AFAIK 这里没有任何“无效”值;只是不是您最初想到的值。因此,就拒绝服务而言,您不必担心太多。请注意,相比之下,decimal 可以 具有无效的二进制表示 - 这些只会引发异常并且单个调用将失败 - 仍然不是拒绝服务(只是:他们会看到失败)。

    不过,我个人建议将double 编码为long 然后编码为string 可能是一种艰难/低效的方式。如果您迫切需要它作为 string,请考虑使用 base-64 对位进行编码。

    【讨论】:

    • 确实,它必须是一个字符串。我没有考虑过base64'ing位。这似乎是一个更好的选择。
    • IEEE 赋予每个位模式一个含义,其中一些表示“无效”(例如,发送信号 NaN)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-10
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2015-02-26
    • 2023-03-21
    • 2021-04-21
    相关资源
    最近更新 更多