You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/08/29 13:01:03 UTC
svn commit: r990541 -
/subversion/branches/performance/subversion/libsvn_subr/cache-membuffer.c
Author: stefan2
Date: Sun Aug 29 11:01:02 2010
New Revision: 990541
URL: http://svn.apache.org/viewvc?rev=990541&view=rev
Log:
Ensure that very large membuffers don't cause internal overflows
due to large items being added (4GB limit could be reached with
64+GB caches) and large number of entries in the dictionary (4G
entry limit would be reached with 3.2TB caches).
* subversion/libsvn_subr/cache-membuffer.c
(get_entry): change parameter type to be consistent with the index
type used everywhere else in this file
(get_index): explicitly cast the result to the correct index type
(svn_cache__membuffer_cache_create): limit the dictionary size
such that entries can be safely addressed using the index type
(svn_membuffer_cache_is_cachable): also, entry sizes must be
representable in 32 bits
Modified:
subversion/branches/performance/subversion/libsvn_subr/cache-membuffer.c
Modified: subversion/branches/performance/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/libsvn_subr/cache-membuffer.c?rev=990541&r1=990540&r2=990541&view=diff
==============================================================================
--- subversion/branches/performance/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/performance/subversion/libsvn_subr/cache-membuffer.c Sun Aug 29 11:01:02 2010
@@ -278,7 +278,7 @@ unlock_cache(svn_membuffer_t *cache, svn
* for the given IDX.
*/
static APR_INLINE entry_t *
-get_entry(svn_membuffer_t *cache, apr_size_t idx)
+get_entry(svn_membuffer_t *cache, apr_uint32_t idx)
{
return &cache->directory[idx / GROUP_SIZE][idx % GROUP_SIZE];
}
@@ -288,7 +288,7 @@ get_entry(svn_membuffer_t *cache, apr_si
static APR_INLINE apr_uint32_t
get_index(svn_membuffer_t *cache, entry_t *entry)
{
- return entry - (entry_t *)cache->directory;
+ return (apr_uint32_t)(entry - (entry_t *)cache->directory);
}
/* Remove the used ENTRY from the CACHE, i.e. make it "unused".
@@ -655,9 +655,18 @@ svn_cache__membuffer_cache_create(svn_me
if (directory_size < sizeof(entry_group_t))
directory_size = sizeof(entry_group_t);
- /* allocate buffers and initialize cache members
+ /* to keep the entries small, we use 32 bit indices only
+ * -> we need to ensure that no more then 4G entries exist
*/
c->group_count = directory_size / sizeof (entry_group_t);
+ if (c->group_count >= (APR_UINT32_MAX / GROUP_SIZE))
+ {
+ c->group_count = (APR_UINT32_MAX / GROUP_SIZE) - 1;
+ directory_size = c->group_count * sizeof (entry_group_t);
+ }
+
+ /* allocate buffers and initialize cache members
+ */
c->directory = apr_palloc(sub_pool, c->group_count * sizeof(entry_group_t));
c->first = -1;
c->last = -1;
@@ -728,6 +737,7 @@ svn_cache__membuffer_cache_create(svn_me
return SVN_NO_ERROR;
}
+
/* Try to insert the ITEM and use the KEY to unqiuely identify it.
* However, there is no guarantee that it will actually be put into
* the cache. If there is already some data associated to the KEY,
@@ -953,6 +963,7 @@ typedef struct svn_membuffer_cache_t
* but not too frequently.
*/
int alloc_counter;
+
} svn_membuffer_cache_t;
/* After an estimated ALLOCATIONS_PER_POOL_CLEAR allocations, we should
@@ -1126,10 +1137,12 @@ static svn_boolean_t
svn_membuffer_cache_is_cachable(void *cache_void, apr_size_t size)
{
/* Don't allow extremely large element sizes. Otherwise, the cache
- * might by thrashed by a few extremely large entries.
+ * might by thrashed by a few extremely large entries. And the size
+ * must be small enough to be stored in a 32 bit value.
*/
svn_membuffer_cache_t *cache = cache_void;
- return size < cache->membuffer->data_size / 16;
+ return (size < cache->membuffer->data_size / 16)
+ && (size < APR_UINT32_MAX - ITEM_ALIGNMENT);
}
/* the v-table for membuffer-based caches
@@ -1170,7 +1183,6 @@ deserialize_svn_stringbuf(void **item,
value_str->data = (char*)buffer;
value_str->len = buffer_size-1;
-
*item = value_str;
return SVN_NO_ERROR;