Possible NULL pointer dereference in GCC's vec code?

Jeff Law suzanne.jeff.law@gmail.com
Mon Feb 11 19:48:00 GMT 2013


Consider this code in va_gc::reserve:


template<typename T, typename A>
void
va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
                 MEM_STAT_DECL)
{
   unsigned alloc
     = vec_prefix::calculate_allocation (v ? &v->vecpfx_ : 0, reserve, 
exact);
   if (!alloc)
     {
       ::ggc_free (v);
       v = NULL;
       return;
     }
[ ... ]


Note how it assigns NULL to v.

Now consider how this gets used in other vec code:

/* If V has no room for one more element, reallocate it.  Then call
    V->quick_push(OBJ).  */
template<typename T, typename A>
inline T *
vec_safe_push (vec<T, A, vl_embed> *&v, const T &obj CXX_MEM_STAT_INFO)
{
   vec_safe_reserve (v, 1, false PASS_MEM_STAT);
   return v->quick_push (obj);
}


/* if V has no room for one more element, reallocate it.  Then call
    V->quick_insert(IX, OBJ).  */
template<typename T, typename A>
inline void
vec_safe_insert (vec<T, A, vl_embed> *&v, unsigned ix, const T &obj
                  CXX_MEM_STAT_INFO)
{
   vec_safe_reserve (v, 1, false PASS_MEM_STAT);
   v->quick_insert (ix, obj);
}


So vec_prefix::calculate_allocation returns NULL, then 
vec_safe_{push,insert} (and possibly others) can dereference a NULL 
pointer if I'm reading the code correctly.

Similarly, the vec_save_{insert,push} will use a pointer after it has 
been freed for heap allocations:


template<typename T>
inline void
va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool 
exact
                   MEM_STAT_DECL)
{
   unsigned alloc
     = vec_prefix::calculate_allocation (v ? &v->vecpfx_ : 0, reserve, 
exact);
   if (!alloc)
     {
       release (v);
       return;
     }
[ ... [

Note how we release v, so we have a use-after-free scenario here if 
vec_prefix::calculate_allocation ever returns null.

Thoughts/comments?

Jeff



More information about the Gcc mailing list