Changeset 25320

Timestamp:
Apr 26, 2021, 4:57:13 PM (3 years ago)
Author:
wraitii
Message:

More actor file validation, preventing crashes.

It's currently possible to trigger ENSUREs in the code if loading empty groups, which is easy enough with LOD and shouldn't happen.

Recover gracefully from these errors instead.

Differential Revision: https://code.wildfiregames.com/D3888

Location:
ps/trunk/source/graphics
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • ps/trunk/source/graphics/ObjectBase.cpp

    r25308 r25320  
    7878}
    7979
    80 void CObjectBase::Load(const CXeromyces& XeroFile, const XMBElement& root)
     80 CObjectBase::Load(const CXeromyces& XeroFile, const XMBElement& root)
    8181{
    8282    // Define all the elements used in the XML file
     
    134134                    continue;
    135135
    136                 LoadVariant(XeroFile, variant, currentGroup.emplace_back());
     136                if (!LoadVariant(XeroFile, variant, currentGroup.emplace_back()))
     137                    return false;
    137138            }
    138139
    139140            if (currentGroup.size() == 0)
     141
    140142                LOGERROR("Actor group has zero variants ('%s')", m_Identifier);
     143
     144
    141145        }
    142146        else if (child_name == el_castshadow)
     
    150154    if (m_Material.empty())
    151155        m_Material = VfsPath("art/materials/default.xml");
    152 }
    153 
    154 void CObjectBase::LoadVariant(const CXeromyces& XeroFile, const XMBElement& variant, Variant& currentVariant)
     156
     157    return true;
     158}
     159
     160bool CObjectBase::LoadVariant(const CXeromyces& XeroFile, const XMBElement& variant, Variant& currentVariant)
    155161{
    156162    #define EL(x) int el_##x = XeroFile.GetElementID(#x)
     
    191197    {
    192198        LOGERROR("Invalid variant format (unrecognised root element '%s')", XeroFile.GetElementString(variant.GetNodeName()).c_str());
    193         return;
     199        return;
    194200    }
    195201
     
    206212            {
    207213                XMBElement variantRoot = XeroVariant.GetRoot();
    208                 LoadVariant(XeroVariant, variantRoot, currentVariant);
     214                if (!LoadVariant(XeroVariant, variantRoot, currentVariant))
     215                    return false;
    209216            }
    210217            else
     218
    211219                LOGERROR("Could not open path %s", attr.Value);
     220
     221
    212222            // Continue loading extra definitions in this variant to allow nested files
    213223        }
     
    234244            XERO_ITER_EL(option, textures_element)
    235245            {
    236                 ENSURE(textures_element.GetNodeName() == el_texture);
     246                if (textures_element.GetNodeName() != el_texture)
     247                {
     248                    LOGERROR("<textures> can only contain <texture> elements.");
     249                    return false;
     250                }
    237251
    238252                Samp samp;
     
    276290            XERO_ITER_EL(option, anim_element)
    277291            {
    278                 ENSURE(anim_element.GetNodeName() == el_animation);
     292                if (anim_element.GetNodeName() != el_animation)
     293                {
     294                    LOGERROR("<animations> can only contain <animations> elements.");
     295                    return false;
     296                }
    279297
    280298                Anim anim;
     
    325343        }
    326344    }
     345
    327346}
    328347
     
    812831    {
    813832        std::unique_ptr<CObjectBase> base = std::make_unique<CObjectBase>(m_ObjectManager, *this, MAX_QUALITY);
    814         base->Load(XeroFile, root);
     833        if (!base->Load(XeroFile, root))
     834        {
     835            LOGERROR("Invalid actor (actor '%s')", pathname.string8());
     836            return false;
     837        }
    815838        m_ObjectBases.emplace_back(std::move(base));
    816839    }
     
    877900                    return false;
    878901                }
    879                 base->Load(XeroFile, inlineActor);
     902                if (!base->Load(XeroFile, inlineActor))
     903                {
     904                    LOGERROR("Invalid inline actor (actor '%s')", pathname.string8());
     905                    return false;
     906                }
     907
    880908            }
    881909            else if (file.empty())
    882                 base->Load(XeroFile, actor);
     910            {
     911                if (!base->Load(XeroFile, actor))
     912                {
     913                    LOGERROR("Invalid actor (actor '%s')", pathname.string8());
     914                    return false;
     915                }
     916            }
    883917            else
    884918            {
     
    897931                        return false;
    898932                    }
    899                     base->Load(XeroActor, root);
     933                    if (!base->Load(XeroActor, root))
     934                    {
     935                        LOGERROR("Invalid actor (actor '%s' loaded from '%s')", file, pathname.string8());
     936                        return false;
     937                    }
    900938                }
    901939                else
  • ps/trunk/source/graphics/ObjectBase.h

    r25308 r25320  
    196196    void GetQualitySplits(std::vector<u8>& splits) const;
    197197
    198     void Load(const CXeromyces& XeroFile, const XMBElement& base);
    199     void LoadVariant(const CXeromyces& XeroFile, const XMBElement& variant, Variant& currentVariant);
     198    Load(const CXeromyces& XeroFile, const XMBElement& base);
     199    LoadVariant(const CXeromyces& XeroFile, const XMBElement& variant, Variant& currentVariant);
    200200
    201201private:
Note: See TracChangeset for help on using the changeset viewer.