Beef up unit tests for SI95 code
[ric-plt/lib/rmr.git] / src / rmr / common / src / symtab.c
index 43acfa1..9fb01bd 100644 (file)
@@ -53,6 +53,7 @@ Mod:          2016 23 Feb - converted Symtab refs so that caller need only a
 #include <stdlib.h>
 #include <memory.h>
 #include <netdb.h>
+#include <pthread.h>
 
 #include "rmr_symtab.h"
 
@@ -84,8 +85,6 @@ static int sym_hash( const char *n, long size )
 {
        const char *p;
        long t = 0;
-       unsigned long tt = 0;
-       unsigned long x = 79;
 
        for( p = n; *p; p++ )      /* a bit of magic */
                t = (t * 79 ) + *p;
@@ -96,7 +95,10 @@ static int sym_hash( const char *n, long size )
        return (int ) (t % size);
 }
 
-/* delete element pointed to by eptr at hash loc hv */
+/*
+       Delete element pointed to by eptr which is assumed to be
+       a member of the list at symtab[i].
+*/
 static void del_ele( Sym_tab *table, int hv, Sym_ele *eptr )
 {
        Sym_ele **sym_tab;
@@ -124,6 +126,39 @@ static void del_ele( Sym_tab *table, int hv, Sym_ele *eptr )
        }
 }
 
+/*
+       Delete the head element from table[i]. This isn't really
+       needed, but keeps code analysers from claiming that memory
+       is being used after it is freed.
+*/
+static void del_head_ele( Sym_tab *table, int hv ) {
+       Sym_ele **sym_tab;
+       Sym_ele *eptr;          // first in list
+
+
+       if( hv < 0 || hv >= table->size ) {
+               return;
+       }
+
+       sym_tab = table->symlist;
+       if( (eptr = sym_tab[hv]) != NULL )                                      // not an empty element; yank it off
+       {
+               if( (sym_tab[hv] = eptr->next) != NULL ) {              // bump list to next if not the only thing here
+                       sym_tab[hv]->prev = NULL;                                       // new head
+               }
+               eptr->next = NULL;                                                              // take no chances
+
+               if( eptr->class && eptr->name ) {                               // class 0 entries are numeric, so name is NOT a pointer
+                       free( (void *) eptr->name );
+               }
+
+               free( eptr );
+
+               table->deaths++;
+               table->inhabitants--;
+       }
+}
+
 /*
        Determine if these are the same.
 */
@@ -143,8 +178,8 @@ static inline int same( unsigned int c1, unsigned int c2, const char *s1, const
        much the same.
 */
 static int putin( Sym_tab *table, const char *name, unsigned int class, void *val ) {
-       Sym_ele *eptr;                  /* pointer into hash table */
-       Sym_ele **sym_tab;      /* pointer into hash table */
+       Sym_ele *eptr;                  /* pointer into hash table */
+       Sym_ele **sym_tab;              /* pointer into hash table */
        int hv;                 /* hash value */
        int rc = 0;             /* assume it existed */
        uint64_t nkey = 0;              // numeric key if class == 0
@@ -160,7 +195,7 @@ static int putin( Sym_tab *table, const char *name, unsigned int class, void *va
                for( eptr=sym_tab[hv]; eptr && eptr->nkey != nkey; eptr=eptr->next );
        }
 
-       if( ! eptr ) {                  // not found above, so add
+       if( ! eptr ) {                  // not found above, so add
                rc++;
                table->inhabitants++;
 
@@ -205,9 +240,11 @@ extern void rmr_sym_clear( void *vtable )
        table = (Sym_tab *) vtable;
        sym_tab = table->symlist;
 
-       for( i = 0; i < table->size; i++ )
-               while( sym_tab[i] )
-                       del_ele( table, i, sym_tab[i] );
+       for( i = 0; i < table->size; i++ ) {
+               while( sym_tab[i] ) {
+                       del_head_ele( table, i );                       // delete the head element (and keep bloody sonar from claiming use after free)
+               }
+       }
 }
 
 /*
@@ -236,15 +273,14 @@ extern void rmr_sym_dump( void *vtable )
        table = (Sym_tab *) vtable;
        sym_tab = table->symlist;
 
-       for( i = 0; i < table->size; i++ )
-       {
-               if( sym_tab[i] )
-               for( eptr = sym_tab[i]; eptr; eptr = eptr->next )
-               {
-                       if( eptr->val && eptr->class ) {
-                               fprintf( stderr, "symtab dump: key=%s val@=%p\n", eptr->name, eptr->val );
-                       } else {
-                               fprintf( stderr, "symtab dump: nkey=%lu val@=%p\n", (unsigned long) eptr->nkey, eptr->val );
+       for( i = 0; i < table->size; i++ ) {
+               if( sym_tab[i] ) {
+                       for( eptr = sym_tab[i]; eptr; eptr = eptr->next ) {
+                               if( eptr->val && eptr->class ) {
+                                       fprintf( stderr, "symtab dump: key=%s val@=%p\n", eptr->name, eptr->val );
+                               } else {
+                                       fprintf( stderr, "symtab dump: nkey=%lu val@=%p\n", (unsigned long) eptr->nkey, eptr->val );
+                               }
                        }
                }
        }
@@ -256,7 +292,6 @@ extern void rmr_sym_dump( void *vtable )
 */
 extern void *rmr_sym_alloc( int size )
 {
-       int i;
        Sym_tab *table;
 
        if( size < 11 )     /* provide a bit of sanity */
@@ -313,7 +348,7 @@ extern void rmr_sym_del( void *vtable, const char *name, unsigned int class )
 /*
        Delete element by numberic key.
 */
-extern void *rmr_sym_ndel(  void *vtable, uint64_t key ) {
+extern void rmr_sym_ndel(  void *vtable, uint64_t key ) {
        rmr_sym_del( vtable, (const char *) &key, 0 );
 }
 
@@ -464,17 +499,22 @@ extern void rmr_sym_foreach_class( void *vst, unsigned int class, void (* user_f
        Sym_ele **list;
        Sym_ele *se;
        Sym_ele *next;          /* allows user to delete the node(s) we return */
-       int     i;
+       int             i;
 
-       st = (Sym_tab *) vst;
+       if( (st = (Sym_tab *) vst) == NULL ) {
+               return;
+       }
 
-       if( st && (list = st->symlist) != NULL && user_fun != NULL )
-               for( i = 0; i < st->size; i++ )
-                       for( se = list[i]; se; se = next )              /* using next allows user to delet via this */
-                       {
-                               next = se->next;
+       if( (list = st->symlist) != NULL && user_fun != NULL ) {
+               for( i = 0; i < st->size; i++ ) {
+                       se = list[i];
+                       while( se ) {
+                               next = se->next;                        // allow callback to delete from the list w/o borking us
                                if( class == se->class ) {
                                        user_fun( st, se, se->name, se->val, user_data );
                                }
+                               se = next;
                        }
+               }
+       }
 }