Hi,

I've noticed that the svn_fs_fs__get_changes function currently invokes
undefined behavior when there is no CHANGES_CACHE present.   According to the
fs_fs_data_t contract, this is a perfectly valid situation (see
subversion\libsvn_fs_fs\fs.h around trunk@1549686):
[[[
  /* Private (non-shared) FSFS-specific data for each svn_fs_t object.
     Any caches in here may be NULL. */
]]]

However, explicitly setting the CHANGES_CACHE to NULL leads to a massive amount
of failing tests (1085 fails on my 64-bit Ubuntu machine, some of them are
segfaults).  This erroneous behavior was introduced in r1512904 [1] and happens
due to the usage of the uninitialized variable FOUND when the CHANGES_CACHE
is absent.  The behavior in this case is undefined and that will likely lead to
a crash.  Here is a tip from valgrind:
[[[
  Conditional jump or move depends on uninitialised value(s)
    at 0x4852AF: svn_fs_fs__get_changes (cached_data.c:2183)
    by 0x469E4C: svn_fs_fs__paths_changed (transaction.c:889)
    by 0x475CDE: fs_paths_changed (tree.c:3291)
    by 0x44DCE7: svn_fs_paths_changed2 (fs-loader.c:1006)
    ...

  Use of uninitialised value of size 8
    at 0x469E8C: svn_fs_fs__paths_changed (transaction.c:892)
    by 0x475CDE: fs_paths_changed (tree.c:3291)
    by 0x44DCE7: svn_fs_paths_changed2 (fs-loader.c:1006)
    ...
]]]

This happens with both FSFS and FSX, so I've attached two patches to fix this
issue (these patches fix the svn_fs_fs__get_changes and svn_fs_x__get_changes
functions accordingly).

[1] http://svn.apache.org/viewvc?view=revision&revision=r1512904


Thanks and regards,
Evgeny Kotkov
Index: subversion/libsvn_fs_fs/cached_data.c
===================================================================
--- subversion/libsvn_fs_fs/cached_data.c       (revision 1549686)
+++ subversion/libsvn_fs_fs/cached_data.c       (working copy)
@@ -2177,8 +2177,14 @@ svn_fs_fs__get_changes(apr_array_header_t **change
   /* try cache lookup first */
 
   if (ffd->changes_cache)
-    SVN_ERR(svn_cache__get((void **) changes, &found, ffd->changes_cache,
-                           &rev, pool));
+    {
+      SVN_ERR(svn_cache__get((void **) changes, &found, ffd->changes_cache,
+                             &rev, pool));
+    }
+  else
+    {
+      found = FALSE;
+    }
 
   if (!found)
     {
Avoid undefined behavior (and crashing) within svn_fs_fs__get_changes when
there is no changes cache.  Caches in fs_fs_data_t are optional by design:
[[[
  /* Private (non-shared) FSFS-specific data for each svn_fs_t object.
     Any caches in here may be NULL. */
]]]

Follow-up to r1512904.

* subversion/libsvn_fs_fs/cached_data.c
  (svn_fs_fs__get_changes): Avoid possible uninitialized variable access by
    setting FOUND to FALSE in case we do not have a CHANGES_CACHE.

Patch by: Evgeny Kotkov <evgeny.kotkov{_AT_}visualsvn.com>
Index: subversion/libsvn_fs_x/cached_data.c
===================================================================
--- subversion/libsvn_fs_x/cached_data.c        (revision 1549686)
+++ subversion/libsvn_fs_x/cached_data.c        (working copy)
@@ -2335,6 +2335,10 @@ svn_fs_x__get_changes(apr_array_header_t **changes
       SVN_ERR(svn_cache__get((void **) changes, &found, ffd->changes_cache,
                              &rev, pool));
     }
+  else
+    {
+      found = FALSE;
+    }
 
   if (!found)
     {
Avoid undefined behavior (and crashing) within svn_fs_x__get_changes when
there are no changes and changes container caches.  Caches in fs_x_data_t are
optional by design:
[[[
  /* Private (non-shared) FSX-specific data for each svn_fs_t object.
     Any caches in here may be NULL. */
]]]

Follow-up to r1508041.

* subversion/libsvn_fs_x/cached_data.c
  (svn_fs_x__get_changes): Avoid possible uninitialized variable access by
    setting FOUND to FALSE in case we do not have CHANGES_CACHE and
    CHANGES_CONTAINER_CACHE.

Patch by: Evgeny Kotkov <evgeny.kotkov{_AT_}visualsvn.com>

Reply via email to