Show
Ignore:
Timestamp:
04/28/11 18:33:14 (4 years ago)
Author:
robert
Message:

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.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/src/osg/CopyOp.cpp

    r10671 r12330  
    2727{ \ 
    2828    if (obj && _flags&FLAG) \ 
    29         return dynamic_cast<TYPE*>( obj->clone(*this) ); \ 
     29        return osg::clone(obj, *this); \ 
    3030    else \ 
    3131        return const_cast<TYPE*>(obj); \ 
    3232}  
    3333 
    34 COPY_OP( Object,         DEEP_COPY_OBJECTS ) 
    35 COPY_OP( Node,           DEEP_COPY_NODES ) 
    36 COPY_OP( Drawable,       DEEP_COPY_DRAWABLES ) 
    37 COPY_OP( StateSet,       DEEP_COPY_STATESETS ) 
    38 COPY_OP( Texture,        DEEP_COPY_TEXTURES ) 
    39 COPY_OP( Image,          DEEP_COPY_IMAGES ) 
    40 COPY_OP( Array,          DEEP_COPY_ARRAYS ) 
    41 COPY_OP( PrimitiveSet,   DEEP_COPY_PRIMITIVES ) 
    42 COPY_OP( Shape,          DEEP_COPY_SHAPES ) 
    43 COPY_OP( Uniform,        DEEP_COPY_UNIFORMS ) 
     34COPY_OP( Object,                   DEEP_COPY_OBJECTS ) 
     35COPY_OP( Node,                     DEEP_COPY_NODES ) 
     36COPY_OP( StateSet,                 DEEP_COPY_STATESETS ) 
     37COPY_OP( Image,                    DEEP_COPY_IMAGES ) 
     38COPY_OP( Uniform,                  DEEP_COPY_UNIFORMS ) 
     39COPY_OP( StateAttributeCallback,   DEEP_COPY_CALLBACKS ) 
     40COPY_OP( Drawable,                 DEEP_COPY_DRAWABLES ) 
     41COPY_OP( Texture,                  DEEP_COPY_TEXTURES ) 
     42COPY_OP( Array,                    DEEP_COPY_ARRAYS ) 
     43COPY_OP( PrimitiveSet,             DEEP_COPY_PRIMITIVES ) 
     44COPY_OP( Shape,                    DEEP_COPY_SHAPES ) 
    4445 
    4546Referenced* CopyOp::operator() (const Referenced* ref) const 
     
    5960        else  
    6061        { 
    61             return dynamic_cast<StateAttribute*>(attr->clone(*this)); 
     62            return osg::clone(attr, *this); 
    6263        } 
    6364    } 
     
    6667} 
    6768 
    68  
    6969NodeCallback* CopyOp::operator() (const NodeCallback* nc) const 
    7070{ 
     
    7272    { 
    7373        // deep copy the full chain of callback 
    74         osg::NodeCallback* first = dynamic_cast<osg::NodeCallback*>(nc->clone(*this)); 
     74        osg::NodeCallback* first = osg::clone(nc, *this); 
     75        if (!first) return 0; 
     76 
    7577        first->setNestedCallback(0); 
    7678        nc = nc->getNestedCallback(); 
    7779        while (nc)  
    7880        { 
    79             osg::NodeCallback* ucb = dynamic_cast<osg::NodeCallback*>(nc->clone(*this)); 
    80             ucb->setNestedCallback(0); 
    81             first->addNestedCallback(ucb); 
     81            osg::NodeCallback* ucb = osg::clone(nc, *this); 
     82            if (ucb) 
     83            { 
     84                ucb->setNestedCallback(0); 
     85                first->addNestedCallback(ucb); 
     86            } 
    8287            nc = nc->getNestedCallback(); 
    8388        } 
     
    8792        return const_cast<NodeCallback*>(nc); 
    8893} 
    89  
    90  
    91 StateAttributeCallback* CopyOp::operator() (const StateAttributeCallback* sc) const 
    92 { 
    93     if (sc && _flags&DEEP_COPY_CALLBACKS) 
    94     { 
    95         // deep copy the full chain of callback 
    96         StateAttributeCallback* cb = dynamic_cast<StateAttributeCallback*>(sc->clone(*this)); 
    97         return cb; 
    98     } 
    99     else 
    100         return const_cast<StateAttributeCallback*>(sc); 
    101 } 
    102