FastNoise2 icon indicating copy to clipboard operation
FastNoise2 copied to clipboard

GenPositionArray2D can index into out of bounds memory

Open Speak2Erase opened this issue 2 years ago • 3 comments

Hi! I'm trying to create a ruby binding for this library but got hung up on something. I'm unsure why this is the case, but in this loop at line 245 of Generator.inl will loop indefinitely and index into out of bounds memory, at least with how I'm calling it. This inevitably causes a segmentation fault.

    // xPosVal & yPosVal are Ruby arrays with the values of [0.0, 1.0]
    // They are converted to std::vectors which definitely contain the values of 0.0 and 1.0
    Array GenPositionArray2D(Object xPosVal, Object yPosVal, float xOffset, float yOffset)
    {
        std::vector<float> xPos = detail::From_Ruby<std::vector<float>>().convert(xPosVal);
        std::vector<float> yPos = detail::From_Ruby<std::vector<float>>().convert(yPosVal);
        
        float minmax[2];
        std::vector<float> noiseOut(xPos.size());
        fnGenPositionArray2D(nodeHandle, noiseOut.data(), xPos.size(), xPos.data(), yPos.data(), xOffset, yOffset, seed, minmax); // Segfault here
        OutputMinMax outputminmax(minmax[0], minmax[1]);

        return gen_result(outputminmax, noiseOut);
    }

After some debugging, I noticed that in the following code, this loop just would not exit, period.

        size_t index = 0;
        while( index < count - FS_Size_32() )
        {
            float32v xPos = float32v( xOffset ) + FS_Load_f32( &xPosArray[index] );
            float32v yPos = float32v( yOffset ) + FS_Load_f32( &yPosArray[index] );

            float32v gen = Gen( int32v( seed ), xPos, yPos );
            FS_Store_f32( &noiseOut[index], gen );

My best guess is that count should be multiplied by FS_Size_32() instead? I'm not super sure though.

>>> info args
this = 0x1ed32db0fd8
noiseOut = 0x1ed3282c420
count = 1
xPosArray = 0x1ed327f4e10
yPosArray = 0x1ed328206d0
xOffset = 0
yOffset = 0
>>> info locals
xPos = {
  vector = {[0] = -nan(0x7fffff), [1] = -nan(0x7fffff), [2] = -nan(0x7fffff), [3] = -nan(0x7fffff), [4] = -nan(0x7fffff), [5] = -nan(0x7fffff), [6] = 0.84829092, [7] = 0.848087311}
}
yPos = {
  vector = {[0] = -nan(0x7fffff), [1] = -nan(0x7fffff), [2] = -nan(0x7fffff), [3] = -nan(0x7fffff), [4] = -nan(0x7fffff), [5] = -nan(0x7fffff), [6] = 0.623758435, [7] = 0.625489891}
}
gen = {
  vector = {[0] = -nan(0x7fffff), [1] = -nan(0x7fffff), [2] = -nan(0x7fffff), [3] = -nan(0x7fffff), [4] = -nan(0x7fffff), [5] = -nan(0x7fffff), [6] = -0.509935439, [7] = -0.509879351}
}
min = {
  vector = {[0] = -nan(0x7fffff), [1] = -nan(0x7fffff), [2] = -nan(0x7fffff), [3] = -nan(0x7fffff), [4] = -nan(0x7fffff), [5] = -nan(0x7fffff), [6] = -nan(0x7fffff), [7] = -nan(0x7fffff)}
}
max = {
  vector = {[0] = -nan(0x7fffff), [1] = -nan(0x7fffff), [2] = -nan(0x7fffff), [3] = -nan(0x7fffff), [4] = -nan(0x7fffff), [5] = -nan(0x7fffff), [6] = -nan(0x7fffff), [7] = -nan(0x7fffff)}
}
index = 559864
xPos = {
  vector = {[0] = -nan(0x7fffff), [1] = -nan(0x7fffff), [2] = -nan(0x7fffff), [3] = -nan(0x7fffff), [4] = -nan(0x7fffff), [5] = -nan(0x7fffff), [6] = 0.84829092, [7] = 0.848087311}
}
yPos = {
  vector = {[0] = -nan(0x7fffff), [1] = -nan(0x7fffff), [2] = -nan(0x7fffff), [3] = -nan(0x7fffff), [4] = -nan(0x7fffff), [5] = -nan(0x7fffff), [6] = 0.623758435, [7] = 0.625489891}
}
gen = {
  vector = {[0] = -nan(0x7fffff), [1] = -nan(0x7fffff), [2] = -nan(0x7fffff), [3] = -nan(0x7fffff), [4] = -nan(0x7fffff), [5] = -nan(0x7fffff), [6] = -0.509935439, [7] = -0.509879351}
}

As you'll notice, index is 559864, which is definitely into out of bounds memory territory. If I had to guess why it takes such a long time to error out, it's probably because I'm running this in Ruby and Ruby is filling up all that memory. I'm no expert at C++ though, I am a rubyist at heart, so I apologize if I got any of this wrong.

I also checked what the value of count - FS_Size_32() is, and it's 18446744073709551611. Yeah...

Speak2Erase avatar Jun 13 '22 07:06 Speak2Erase

Looks like an underflow issue with 'count - FS_SIZE()' what is the size of the vector you are passing in. If it is >=8 you likely won't have the issue.

I will look at a fix for this

Auburn avatar Jun 13 '22 09:06 Auburn

Ok, thank you!

Speak2Erase avatar Jun 13 '22 20:06 Speak2Erase

It seems fnGenUniformGrid2D related functions also have the same issue. I can confirm that with length >=8 it works fine though.

findmyway avatar Aug 08 '22 10:08 findmyway

Same thing when using GenUniformGrid3D, while getting a single column value.

_noiseGenerator->GenUniformGrid3D(
		noise.data(),
		x, y, z,
		1, size, 1,
		_frequency, _seed);

RooTender avatar Aug 31 '22 06:08 RooTender