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 2012/09/11 02:18:50 UTC

svn commit: r1383180 - /subversion/trunk/subversion/libsvn_subr/cache-membuffer.c

Author: stefan2
Date: Tue Sep 11 00:18:50 2012
New Revision: 1383180

URL: http://svn.apache.org/viewvc?rev=1383180&view=rev
Log:
Fix a subtle buffer overflow in the membuffer cache when the data buffer
size is not a multiple of 16 bytes (ITEM_ALIGNMENT).  Because we will
move the insertion pointer always in multiples of ITEM_ALIGMENT, it could
then be moved to a position behind the buffer where capacity - position < 0.

Also, fix two small style and spelling issues.

* subversion/libsvn_subr/cache-membuffer.c
  (insert_entry, move_entry): add assertions to debug overflows in future
  (ensure_data_insertable): make condition immune to overflows
  (svn_cache__membuffer_cache_create): actual fix
  (drop_entry): minor formatting fix
  (membuffer_cache_set_internal): fix typo

Modified:
    subversion/trunk/subversion/libsvn_subr/cache-membuffer.c

Modified: subversion/trunk/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cache-membuffer.c?rev=1383180&r1=1383179&r2=1383180&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cache-membuffer.c Tue Sep 11 00:18:50 2012
@@ -576,7 +576,7 @@ drop_entry(svn_membuffer_t *cache, entry
             /* remove the first entry -> insertion may start at pos 0, now */
             cache->current_data = 0;
           }
-          else
+        else
           {
             /* insertion may start right behind the previous entry */
             entry_t *previous = get_entry(cache, entry->previous);
@@ -658,6 +658,11 @@ insert_entry(svn_membuffer_t *cache, ent
       else
         cache->first = idx;
     }
+
+  /* The current insertion position must never point outside our
+   * data buffer.
+   */
+  assert(cache->current_data <= cache->data_size);
 }
 
 /* Map a KEY of 16 bytes to the CACHE and group that shall contain the
@@ -857,6 +862,11 @@ move_entry(svn_membuffer_t *cache, entry
    */
   cache->current_data = entry->offset + size;
   cache->next = entry->next;
+
+  /* The current insertion position must never point outside our
+   * data buffer.
+   */
+  assert(cache->current_data <= cache->data_size);
 }
 
 /* If necessary, enlarge the insertion window until it is at least
@@ -898,7 +908,7 @@ ensure_data_insertable(svn_membuffer_t *
 
       /* leave function as soon as the insertion window is large enough
        */
-      if (end - cache->current_data >= size)
+      if (end >= size + cache->current_data)
         return TRUE;
 
       /* Don't be too eager to cache data. Smaller items will fit into
@@ -1055,8 +1065,10 @@ svn_cache__membuffer_cache_create(svn_me
 
   /* limit the data size to what we can address.
    * Note that this cannot overflow since all values are of size_t.
+   * Also, make it a multiple of the item placement granularity to
+   * prevent subtle overflows.
    */
-  data_size = total_size - directory_size;
+  data_size = ALIGN_VALUE(total_size - directory_size + 1) - ITEM_ALIGNMENT;
 
   /* For cache sizes > 4TB, individual cache segments will be larger
    * than 16GB allowing for >4GB entries.  But caching chunks larger
@@ -1190,7 +1202,7 @@ membuffer_cache_set_internal(svn_membuff
         {
           /* Remove old data for this key, if that exists.
            * Get an unused entry for the key and and initialize it with
-           * the serialized item's (future) posion within data buffer.
+           * the serialized item's (future) position within data buffer.
            */
           entry = find_entry(cache, group_index, to_find, TRUE);
           entry->size = size;