OpenSceneGraph/src/osg/CopyOp.cpp
Robert Osfield 41eb850578 Fixed Coverity reported issue.
CID 11447: Unchecked dynamic_cast (FORWARD_NULL)
Dynamic cast to pointer "dynamic_cast <struct osg::NodeCallback *>(nc->clone(this))" can return null.
Assigning null: "first" = "dynamic_cast <struct osg::NodeCallback *>(nc->clone(this))".

The clone() implementation is written using macro's so that it always returns the type of Object
being cloned so it's normally safe to assume that a dynamic_cast<> will always return a valid pointer as long
as the new T that involves creates a valid object.  However, if the class being cloned doesn't correctly
implement the clone() method then their potential for the dynamic_cast to fail and will return a NULL and will
result in a memory leak of the object of paraent class that the clone would have defaulted to.

I've tightened up the CopyOp.cpp code to check the return type and added better handling of the clone in the
osg::clone() methods so thay don't have any potential mememory leaks and report warnings to OSG_WARN when
problems are encountered.  It may be more apporpriate to throw an exception so will need to ponder this
issue further.
2011-04-28 16:33:14 +00:00

94 lines
2.9 KiB
C++

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osg/CopyOp>
#include <osg/Node>
#include <osg/StateSet>
#include <osg/Texture>
#include <osg/Drawable>
#include <osg/Array>
#include <osg/PrimitiveSet>
#include <osg/Shape>
#include <osg/StateAttribute>
using namespace osg;
#define COPY_OP( TYPE, FLAG ) \
TYPE* CopyOp::operator() (const TYPE* obj) const \
{ \
if (obj && _flags&FLAG) \
return osg::clone(obj, *this); \
else \
return const_cast<TYPE*>(obj); \
}
COPY_OP( Object, DEEP_COPY_OBJECTS )
COPY_OP( Node, DEEP_COPY_NODES )
COPY_OP( StateSet, DEEP_COPY_STATESETS )
COPY_OP( Image, DEEP_COPY_IMAGES )
COPY_OP( Uniform, DEEP_COPY_UNIFORMS )
COPY_OP( StateAttributeCallback, DEEP_COPY_CALLBACKS )
COPY_OP( Drawable, DEEP_COPY_DRAWABLES )
COPY_OP( Texture, DEEP_COPY_TEXTURES )
COPY_OP( Array, DEEP_COPY_ARRAYS )
COPY_OP( PrimitiveSet, DEEP_COPY_PRIMITIVES )
COPY_OP( Shape, DEEP_COPY_SHAPES )
Referenced* CopyOp::operator() (const Referenced* ref) const
{
return const_cast<Referenced*>(ref);
}
StateAttribute* CopyOp::operator() (const StateAttribute* attr) const
{
if (attr && _flags&DEEP_COPY_STATEATTRIBUTES)
{
const Texture* textbase = dynamic_cast<const Texture*>(attr);
if (textbase)
{
return operator()(textbase);
}
else
{
return osg::clone(attr, *this);
}
}
else
return const_cast<StateAttribute*>(attr);
}
NodeCallback* CopyOp::operator() (const NodeCallback* nc) const
{
if (nc && _flags&DEEP_COPY_CALLBACKS)
{
// deep copy the full chain of callback
osg::NodeCallback* first = osg::clone(nc, *this);
if (!first) return 0;
first->setNestedCallback(0);
nc = nc->getNestedCallback();
while (nc)
{
osg::NodeCallback* ucb = osg::clone(nc, *this);
if (ucb)
{
ucb->setNestedCallback(0);
first->addNestedCallback(ucb);
}
nc = nc->getNestedCallback();
}
return first;
}
else
return const_cast<NodeCallback*>(nc);
}