summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsuzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>2011-01-09 23:09:36 +0900
committersuzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>2011-01-09 23:09:36 +0900
commit5e7ad208e35643e18deb505465604e2ed3b149cf (patch)
tree53ccd8d1580ca9b3c2530557aa82df776ea1b90c
parent38b272ffbbdaae276d636aec4ef84af407d16181 (diff)
downloadfreetype2-5e7ad208e35643e18deb505465604e2ed3b149cf.tar.gz
[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.
-rw-r--r--ChangeLog17
-rw-r--r--src/cache/ftccache.c23
-rw-r--r--src/cache/ftccache.h24
3 files changed, 64 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 182476cf4..af8c8fea7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
2010-01-09 suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
+ [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 <mpsuzuki@hiroshima-u.ac.jp>
+
[cache] Notice if a cache query induced the node list change.
Some node comparators (comparing the cache node content and
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; \