Skip to content

Segfault in Grid Interpolation #625

Description

@dbs4261

Hi folks, I've been trying to debug a segfault I have been getting in a python c extension that statically links to Embree. The program does not crash on Linux. The crash happens in the Windows deployment of the c extension, though I haven't been able to reproduce the crash in a C++ only test script. That said, stepping through with the debugger shows an out of bounds index is generated, even if it isn't read from. I think it might have to do with the size of the grid and how far out of bounds I need to be for the error to be generated, but I'm not sure.

I get Exception: Exception 0xc0000005 encountered at address 0x7ff77e978b48: Access violation reading location 0x1fcf232e068 at

const vfloat<N> p2 = mem<vfloat<N>>::loadu(valid,(float*)&src[(idx1+1)*stride+ofs]);

This to be because Embree always reads the row and then the row after it to get the two corners of the interpolation in that direction. When passing a V coordinate of 1.0, which is supposed to be valid based on the comment on line 74

/* clamp input u,v to [0;1] range */
U = max(min(U,1.0f),0.0f);
V = max(min(V,1.0f),0.0f);

The resulting index is past the end of the of the array.
const unsigned int idx1 = grid.startVtxID + (iv+1)*grid.lineVtxOffset + iu;

I can think of two solutions. The simplest solution is to make the maximum V value nextowards(1.0f, 0.0f) so that 1 is not included, but the resulting values might be slightly off, and it involves the full bilinear interpolation. The correct approach would be switching to a linear interpolation when V is identically equal to 1.0f.

Here is a test snippet. On my machine, it does not segfault, but the debugger shows the invalid index.

#include <array>
#include <print>
#include <limits>

#include "embree4/rtcore.h"

int main() {
    RTCDevice device = rtcNewDevice(nullptr);
    RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_GRID);
    std::array<float, 3 * 5 * 5 + 1> vertices{
        0.0f,  0.0f, 0.0f,
        0.25f, 0.0f, 0.0f,
        0.50f, 0.0f, 0.0f,
        0.75f, 0.0f, 0.0f,
        1.0f,  0.0f, 0.0f,
        0.0f,  0.25f, 0.0f,
        0.25f, 0.25f, 0.0f,
        0.50f, 0.25f, 0.0f,
        0.75f, 0.25f, 0.0f,
        1.0f,  0.25f, 0.0f,
        0.0f,  0.50f, 0.0f,
        0.25f, 0.50f, 0.0f,
        0.50f, 0.50f, 0.0f,
        0.75f, 0.50f, 0.0f,
        1.0f,  0.50f, 0.0f,
        0.0f,  0.75f, 0.0f,
        0.25f, 0.75f, 0.0f,
        0.50f, 0.75f, 0.0f,
        0.75f, 0.75f, 0.0f,
        1.0f,  0.75f, 0.0f,
        0.0f,  1.00f, 0.0f,
        0.25f, 1.00f, 0.0f,
        0.50f, 1.00f, 0.0f,
        0.75f, 1.00f, 0.0f,
        1.0f,  1.00f, 0.0f,
        std::numeric_limits<float>::quiet_NaN()
    };
    rtcSetSharedGeometryBuffer(geom, RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3,
        vertices.data(), 0, sizeof(float) * 3, 25);
    auto& grid = *reinterpret_cast<RTCGrid*>(rtcSetNewGeometryBuffer(geom,
        RTC_BUFFER_TYPE_GRID, 0, RTC_FORMAT_GRID, sizeof(RTCGrid), 1));
    grid.startVertexID = 0;
    grid.stride = 5;
    grid.width = 5;
    grid.height = 5;
    rtcCommitGeometry(geom);
    std::array<float, 3> result{};
    RTCInterpolateArguments args{
        .geometry = geom,
        .primID = 0,
        .u = 1.0,
        .v = 1.0,
        .bufferType = RTC_BUFFER_TYPE_VERTEX,
        .bufferSlot = 0,
        .P = result.data(),
        .dPdu = nullptr,
        .dPdv = nullptr,
        .ddPdudu = nullptr,
        .ddPdvdv = nullptr,
        .ddPdudv = nullptr,
        .valueCount = 3,
    };
    rtcInterpolate(&args);
    std::println("Result: {}, {}, {}", result[0], result[1], result[2]);
    rtcReleaseGeometry(geom);
    rtcReleaseDevice(device);
    return 0;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions