diff --git a/ChangeLog b/ChangeLog index 182476cf4..af8c8fea7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2010-01-09 suzuki toshiya + + [cache] Fix Savannah bug #31923, patch drafted by Harsha. + + When a node comparator changes the cached nodes during the + search of a node matching with queried properties, the + pointers obtained before the functon should be updated to + prevent the dereference to freed or reallocated nodes. + To minimize the rescan of the linked list, the update is + executed when the comparator notifies the change of cached + nodes. This change depends previous change: + 38b272ffbbdaae276d636aec4ef84af407d16181 + + * src/cache/ftccache.h (FTC_CACHE_LOOKUP_CMP): Rescan the + top node if the cached nodes are changed. + * src/cache/ftccache.c (FTC_Cache_Lookup): Ditto. + 2010-01-09 suzuki toshiya [cache] Notice if a cache query induced the node list change. diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c index 9a5256017..ad1c5c307 100644 --- a/src/cache/ftccache.c +++ b/src/cache/ftccache.c @@ -498,7 +498,11 @@ if ( cache == NULL || anode == NULL ) return FTC_Err_Invalid_Argument; + /* Go to the `top' node of the list sharing same masked hash */ bucket = pnode = FTC_NODE__TOP_FOR_HASH( cache, hash ); + + /* Lookup a node with exactly same hash and queried properties. */ + /* NOTE: _nodcomp() may change the linked list to reduce memory. */ for (;;) { node = *pnode; @@ -512,6 +516,25 @@ pnode = &node->link; } + if ( list_changed ) + { + /* Update bucket by modified linked list */ + bucket = pnode = FTC_NODE__TOP_FOR_HASH( cache, hash ); + + /* Update pnode by modified linked list */ + while ( *pnode != node ) + { + if ( *pnode == NULL ) + { + FT_ERROR(("oops!!! node missing")); + goto NewNode; + } + else + pnode = &((*pnode)->link); + } + } + + /* Reorder the list to move the found node to the `top' */ if ( node != *bucket ) { *pnode = node->link; diff --git a/src/cache/ftccache.h b/src/cache/ftccache.h index b6b40a01f..d696621e7 100644 --- a/src/cache/ftccache.h +++ b/src/cache/ftccache.h @@ -224,8 +224,12 @@ FT_BEGIN_HEADER \ error = FTC_Err_Ok; \ node = NULL; \ + \ + /* Go to the `top' node of the list sharing same masked hash */ \ _bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash ); \ \ + /* Lookup a node with exactly same hash and queried properties. */ \ + /* NOTE: _nodcomp() may change the linked list to reduce memory. */ \ for (;;) \ { \ _node = *_pnode; \ @@ -239,6 +243,25 @@ FT_BEGIN_HEADER _pnode = &_node->link; \ } \ \ + if ( _list_changed ) \ + { \ + /* Update _bucket by possibly modified linked list */ \ + _bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash ); \ + \ + /* Update _pnode by possibly modified linked list */ \ + while ( *_pnode != _node ) \ + { \ + if ( *_pnode == NULL ) \ + { \ + FT_ERROR(("oops!!! node missing")); \ + goto _NewNode; \ + } \ + else \ + _pnode = &((*_pnode)->link); \ + } \ + } \ + \ + /* Reorder the list to move the found node to the `top' */ \ if ( _node != *_bucket ) \ { \ *_pnode = _node->link; \ @@ -246,6 +269,7 @@ FT_BEGIN_HEADER *_bucket = _node; \ } \ \ + /* Update MRU list */ \ { \ FTC_Manager _manager = _cache->manager; \ void* _nl = &_manager->nodes_list; \