-1

In my application I create an array with a predefined size which is then fixed, and filled by an unmanaged lib. This works fine as long as the application is build using Visual Studio 2017, but if the application is build using Visual Studio 2019 the array size stops making any sense. How can the length of an array be negative?

//edit

The long length is the same: .

The buffer is a completly normal byte array

_buffer = new byte[BufferSize];

The method is just a simple wrapper around the official zlib dll. How could an error in this method confuse .net about the size of an array?

fixed (byte* inputPtr = input)
fixed (byte* bufPtr = _buffer)
{
    _zStreamHandle.ZStream.nextIn = (IntPtr)inputPtr;
    _zStreamHandle.ZStream.availIn = length;
    _zStreamHandle.ZStream.nextOut = (IntPtr)bufPtr;
    _zStreamHandle.ZStream.availOut = BufferSize;
    var dataLeft = false;

    while (_zStreamHandle.ZStream.availIn != 0 || dataLeft)
    {
        var state = _zStreamHandle.Deflate(_flushMode);

        if (state != ErrorCode.Ok)
            throw new VncException("ZStream error: " + state);

        var outCount = BufferSize - (int) _zStreamHandle.ZStream.availOut;
        dataLeft = _zStreamHandle.ZStream.availOut == 0;

        try
        {
            _baseStream.Write(_buffer, 0, outCount);
        }
        catch (Exception e)
        {
            var bufferLength = _buffer.Length;
            var bufferLongLength = _buffer.LongLength;
            Debugger.Break();
        }

        _zStreamHandle.ZStream.nextOut = (IntPtr)bufPtr;
        _zStreamHandle.ZStream.availOut = BufferSize;
    }
}
D Stanley
  • 149,601
  • 11
  • 178
  • 240
Betabot
  • 43
  • 6
  • Really strange. Show us some code. Maybe how the array was created and filled. – Pedro Lima Apr 15 '20 at 11:14
  • What do you mean by "a 64 bit number"? -14,013,908 is within the range of `int`. (`int.MinValue` is -2,147,483,648). My guess is that the unmanaged library is doing something very wrong, but it would be much easier to say if we could reproduce the problem. – Jon Skeet Apr 15 '20 at 11:14
  • 1
    Have you tried calling `.LongLength` instead of `.Length`? – Pedro Lima Apr 15 '20 at 11:16
  • @JonSkeet I misread the number as -14 billion instead of -14 million, but how could an unmanaged library with is only getting the fixed pointer to the array change the runtimes understanding of the length of the array? – Betabot Apr 15 '20 at 12:28
  • @Betabot: I believe the length of an array comes just before the actual data in memory. So if the unmanaged code is badly behaved and stomps on the memory just before the data, that would change the array length. – Jon Skeet Apr 15 '20 at 13:09

1 Answers1

3

I believe the unmanaged code is stomping on the memory just before the start of the array data itself. You can simulate this with managed unsafe code. The exact results may well depend on the CLR, but on my machine this code makes .NET think the length of the array is -1:

using System;

class Test
{
    unsafe static void Main()
    {
        byte[] array = new byte[20];
        Console.WriteLine(array.Length);
        fixed (byte* b = array)
        {
            // On my machine, the length of the array starts
            // 8 bytes before the array data itself
            byte* lengthPtr = b - 8;

            // So let's stop on those four bytes...
            *lengthPtr++ = 255;
            *lengthPtr++ = 255;
            *lengthPtr++ = 255;
            *lengthPtr++ = 255;
        }

        // Prints -1
        Console.WriteLine(array.Length);
    }
}

So basically you need to fix the unmanaged library in your case. It may be that there's a 32-bit/64-bit problem somewhere - I would advise you to check that everything expects the same architecture.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • This seams to be the problem. The bug only happens when using vs2019 and while running the software in 64bit mode. With vs2017 both 32bit and 64bit work. The library with the correct bitness is loaded at runtime. I do not believe the errror is somewhere in zlib, so my handling of it must be wrong in a way that only happens in vs2019. – Betabot Apr 16 '20 at 12:22