Skip to content

nulldref possible on Switch block #3067

Description

@seang-ilm

A tidied up fuzz finding. This one's on a highly infeasible path.

You'll only see it triggered if you have MATERIALX_DYNAMIC_ANALYSIS=ON.

If you add this test case to MaterialXTest/MaterialXCore/Document.cpp

TEST_CASE("Document upgrade switch null value", "[document]")
{
    mx::DocumentPtr doc = mx::createDocument();
    mx::XmlReadOptions readOptions;
    readOptions.upgradeVersion = false;
    mx::readFromXmlString(
        doc,
        R"(<?xml version="1.0"?>
            <materialx version="1.38">
            <nodegraph name="NG1">
                <switch name="sw1" type="integer" nodedef="ND_switch">
                    <input name="which" type="integer" value="abc"/>
                </switch>
            </nodegraph>
            </materialx>
            )",
        mx::FileSearchPath(),
        &readOptions
    );
    REQUIRE_NOTHROW(doc->upgradeVersion());
}
/home/sean/MaterialX/source/MaterialXCore/Version.cpp:1171:45: runtime error: member call on null pointer of type 'struct element_type'

It looks like it's specifically in the upgrade path for 1.38-1.39. When which can't be parsed it returns null.

I think it just needs a null check before accessing it in this block.

void Document::upgradeVersion()
...

    // Upgrade from 1.38 to 1.39
    if (majorVersion == 1 && minorVersion == 38)

            else if (nodeCategory == "switch")
            {
                // Upgrade switch nodes from 5 to 10 inputs, handling the fallback behavior for
                // constant "which" values that were previously out of range.
                InputPtr which = node->getInput("which");
                if (which && which->hasValue())
                {
                    auto whichValue = which->getValue(); // <-- returns null
                    if (whichValue->isA<int>() && whichValue->asA<int>() >= 5) // <-- nulldref here

else if (nodeCategory == "switch")
{
// Upgrade switch nodes from 5 to 10 inputs, handling the fallback behavior for
// constant "which" values that were previously out of range.
InputPtr which = node->getInput("which");
if (which && which->hasValue())
{
auto whichValue = which->getValue();
if (whichValue->isA<int>() && whichValue->asA<int>() >= 5)
{
which->setValue(0);
}
else if (whichValue->isA<float>() && whichValue->asA<float>() >= 5)
{
which->setValue(0.0);
}
}
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions