C# 安全访问MemoryStream中的数据
假设我有一个C# 安全访问MemoryStream中的数据,c#,bytearray,memorystream,C#,Bytearray,Memorystream,假设我有一个MemoryStream和对字节进行操作的函数 当前代码如下所示: void caller() { MemoryStream ms = // not important func(ms.GetBuffer(), 0, (int)ms.Length); } void func(byte[] buffer, int offset, int length) { // not important } 我无法更改func,但我希望尽量减少从func中更改流数据的可能
MemoryStream
和对字节进行操作的函数
当前代码如下所示:
void caller()
{
MemoryStream ms = // not important
func(ms.GetBuffer(), 0, (int)ms.Length);
}
void func(byte[] buffer, int offset, int length)
{
// not important
}
我无法更改func
,但我希望尽量减少从func
中更改流数据的可能性
我如何/应该重写代码以确保流数据不会更改
或者这不能做到
编辑:
很抱歉,我没有提到a我不想复制数据。使用
ms.ToArray()从流中复制数据。
。显然,性能会受到影响。调用。ToArray
func(ms.GetBuffer().ToArray(), 0, (int)ms.Length);
来自(我的):
请注意,缓冲区包含可能未使用的已分配字节。
例如,如果字符串“test”被写入MemoryStream中
对象,则从GetBuffer返回的缓冲区长度为256,而不是
4,其中252个字节未使用要仅获取缓冲区中的数据,请使用
ToArray方法;但是,ToArray会在中创建数据的副本
内存。
理想情况下,您可以将
func
更改为使用IEnumerable
。一旦一个方法拥有了数组,你就相信如果你不希望他们修改数据,他们不会修改数据。如果契约提供的是IEnumerable
,则实现者必须决定是否需要一个副本进行编辑。不能仅将数组的“切片”传递给方法。将数组的副本传递给方法并将结果复制回:
byte[] slice = new byte[length];
Buffer.BlockCopy(bytes, offset, slice, 0, length);
func(slice, 0, length);
Buffer.BlockCopy(slice, 0, bytes, offset, length);
或者,如果可以更改方法,则传递某种代理对象,该对象包装数组并检查每次访问是否在允许的范围内:
class ArrayView<T>
{
private T[] array;
private int offset;
private int length;
public T this[int index]
{
get
{
if (index < offset || index >= offset + length)
throw new ArgumentOutOfRange("index");
return array[index];
}
set
{
if (index < offset || index >= offset + length)
throw new ArgumentOutOfRange("index");
array[index] = value;
}
}
}
类阵列视图
{
私有T[]数组;
私有整数偏移;
私有整数长度;
公共T此[int索引]
{
得到
{
如果(索引<偏移量| |索引>=偏移量+长度)
抛出新的ArgumentOutOfRange(“索引”);
返回数组[索引];
}
设置
{
如果(索引<偏移量| |索引>=偏移量+长度)
抛出新的ArgumentOutOfRange(“索引”);
数组[索引]=值;
}
}
}
如果您无法复制(按照其他答案中的建议排列)并且无法更改func
函数的签名,唯一剩下的就是尝试验证该函数没有更改数据
您可以在调用之前/之后计算某种散列,并检查它是否相同。它不能保证func没有更改基础数据(由于散列冲突),但至少可以让您知道是否发生了更改。可能对非生产代码有用
真正的解决方案是要么向不受信任的代码提供数据副本,要么传递一些不允许数据更改的包装器接口/对象(需要对
func
进行签名更改/重写)。您是否试图确保func()
永远无法更改内存流,或者,如果您的代码在发生更改时可以引发异常,这就足够了吗?听起来你想做以下事情:
void caller()
{
MemoryStream ms = // not important
var checksum = CalculateMyChecksum(ms);
func(ms.GetBuffer(), 0, (int)ms.Length);
if(checksum != CalculateMyChecksum(ms)){
throw new Exception("Hey! Someone has been fiddling with my memory!");
}
}
不过,对于任何重要/关键的事情,我都不愿意推荐这个。你能提供更多的信息吗?也许有更好的方法来解决你的问题,并且完全避免这个问题