https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94858

            Bug ID: 94858
           Summary: False report of memory leak
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: analyzer
          Assignee: dmalcolm at gcc dot gnu.org
          Reporter: addw at phcomp dot co.uk
  Target Milestone: ---

Report of a memory leak - that does not happen.
If malloc()/realloc() fails then td->hs_index is left untouched. 

#include <stdlib.h>                                                             

#define FALSE   0                                                               
#define TRUE    1                                                               
#define HASH_EMPTY      -1                                                      

typedef short   hashNx;                                                         

typedef struct  hashSt  {                                                       
        hashNx* hs_index;       // Indicies into table - hashed to find index   
        int     hs_used;        // Entries used in hs_index                     
        int     hs_slots;       // Available slots in hs_index                  
} hashSt;                                                                       

void    hashEmpty(hashSt* td);                                                  

int     hashAlloc(hashSt* td, int slots)                                        
{                                                                               
        hashNx* index;                                                          

        // Is the index already at least that big ?                             
        if(slots > td->hs_slots) {                                              

                // New or reallocate ?                                          
                if(td->hs_index != NULL)                                        
                        index = realloc(td->hs_index, (size_t)slots *
sizeof(hashNx));                                
                else                                                            
                        index = malloc((size_t)slots * sizeof(hashNx));         

                if(index == NULL)                                               
                        return(FALSE);                                          

                // If we get here malloc()/realloc() worked                     
                td->hs_index = index;                                           
                td->hs_slots = slots;                                           
        }                                                                       

        hashEmpty(td);  // Clear the index                                      

        return(TRUE);                                                           
}                                                                               

/* Mark everything in the hash index as empty.                                  
 * This is useful if you have deleted something and need to reindex.            
 * It is OK to call this on a table that has not been initialised.              
 */                                                                             
void    hashEmpty(hashSt* td)                                                   
{                                                                               
        hashNx* index;                                                          
        int     slots;                                                          

        for(slots = td->hs_slots, index = td->hs_index; --slots >= 0; )         
                *index++ = HASH_EMPTY;                                          

        td->hs_used = 0;                                                        
}                                                                               


cc -O2 -Wall -Wno-pointer-sign -Wconversion -fanalyzer -c -o hasha.o hasha.c    

In function ‘hashAlloc’:                                                        
hasha.c:54:14: warning: leak of ‘index’ [CWE-401] [-Wanalyzer-malloc-leak]      
   54 |  td->hs_used = 0;                                                       
      |  ~~~~~~~~~~~~^~~                                                        
  ‘hashAlloc’: events 1-9                                                       
    |                                                                           
    |   22 |  if(slots > td->hs_slots) {                                        
    |      |    ^
    |      |    |
    |      |    (1) following ‘true’ branch...
    |......                                                                     
    |   25 |   if(td->hs_index != NULL)                                         
    |      |     ~~~~~~~~~~~~~                                                  
    |      |     |  |                                                           
    |      |     |  (2) ...to here
    |      |     (3) following ‘false’ branch...                                
    |......
    |   28 |    index = malloc((size_t)slots * sizeof(hashNx));                 
    |      |                   ~~~~~~~~~~~~~
    |      |                   |                                                
    |      |                   (4) ...to here                                   
    |      |                   (5) allocated here                               
    |   29 |
    |   30 |   if(index == NULL)
    |      |     ~                                                              
    |      |     |
    |      |     (6) assuming ‘index’ is non-NULL                               
    |      |     (7) following ‘false’ branch (when ‘index’ is non-NULL)...     
    |......
    |   33 |   td->hs_index = index;                                            
    |      |   ~~~~~~~~~~~~~~~~~~~~
    |      |                |
    |      |                (8) ...to here                                      
    |......                                                                     
    |   54 |  td->hs_used = 0;                                                  
    |      |  ~~~~~~~~~~~~~~~
    |      |              |                                                     
    |      |              (9) ‘index’ leaks here; was allocated at (5)          
    |

Reply via email to