Stefan,

How about the following patch to sanity check the rev file footer?

[[[
fsfs7: Validate index offsets in rev file footer.

* subversion/libsvn_fs_fs/low_level.c
  (svn_fs_fs__parse_footer): Take FILESIZE argument, use it for validation.

* subversion/libsvn_fs_fs/low_level.h
  (svn_fs_fs__parse_footer): Take FILESIZE argument.

* subversion/libsvn_fs_fs/rev_file.c
  (svn_fs_fs__auto_read_footer): Pass FILESIZE.
]]]

[[[
Index: subversion/libsvn_fs_fs/low_level.c
===================================================================
--- subversion/libsvn_fs_fs/low_level.c (revision 1679906)
+++ subversion/libsvn_fs_fs/low_level.c (working copy)
@@ -196,9 +196,10 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_offset,
                         svn_checksum_t **p2l_checksum,
                         svn_stringbuf_t *footer,
                         svn_revnum_t rev,
+                        svn_filesize_t filesize,
                         apr_pool_t *result_pool)
 {
-  apr_int64_t val;
+  apr_uint64_t val;
   char *last_str = footer->data;
 
   /* Get the L2P offset. */
@@ -207,7 +208,8 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_offset,
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Invalid revision footer"));
 
-  SVN_ERR(svn_cstring_atoi64(&val, str));
+  SVN_ERR_W(svn_cstring_strtoui64(&val, str, 0, filesize-1, 10),
+            "Invalid L2P offset in revision footer");
   *l2p_offset = (apr_off_t)val;
 
   /* Get the L2P checksum. */
@@ -225,7 +227,9 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_offset,
     return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                             _("Invalid revision footer"));
 
-  SVN_ERR(svn_cstring_atoi64(&val, str));
+  SVN_ERR_W(svn_cstring_strtoui64(&val, str, 0, filesize-1, 10),
+            "Invalid P2L offset in revision footer");
+
   *p2l_offset = (apr_off_t)val;
 
   /* Get the P2L checksum. */
Index: subversion/libsvn_fs_fs/low_level.h
===================================================================
--- subversion/libsvn_fs_fs/low_level.h (revision 1679906)
+++ subversion/libsvn_fs_fs/low_level.h (working copy)
@@ -67,6 +67,8 @@ svn_fs_fs__unparse_revision_trailer(apr_off_t root
  * *P2L_OFFSET, respectively.  Also, return the expected checksums in
  * in *L2P_CHECKSUM and *P2L_CHECKSUM.
  *
+ * FILESIZE is used for validation.
+ *
  * Note that REV is only used to construct nicer error objects that
  * mention this revision.  Allocate the checksums in RESULT_POOL.
  */
@@ -77,6 +79,7 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_offset,
                         svn_checksum_t **p2l_checksum,
                         svn_stringbuf_t *footer,
                         svn_revnum_t rev,
+                        svn_filesize_t filesize,
                         apr_pool_t *result_pool);
 
 /* Given the offset of the L2P index data in L2P_OFFSET, the content
Index: subversion/libsvn_fs_fs/rev_file.c
===================================================================
--- subversion/libsvn_fs_fs/rev_file.c  (revision 1679906)
+++ subversion/libsvn_fs_fs/rev_file.c  (working copy)
@@ -259,7 +259,9 @@ svn_fs_fs__auto_read_footer(svn_fs_fs__revision_fi
       SVN_ERR(svn_fs_fs__parse_footer(&file->l2p_offset, &file->l2p_checksum,
                                       &file->p2l_offset, &file->p2l_checksum,
                                       footer, file->start_revision,
+                                      filesize,
                                       file->pool));
+
       file->footer_offset = filesize - footer_length - 1;
     }
 
]]]

The error looks like this:

    subversion/libsvn_fs_fs/rev_file.c:263,
    subversion/libsvn_fs_fs/low_level.c:212: (apr_err=SVN_ERR_INCORRECT_PARAMS)
    svn: E200004: Invalid L2P offset in revision footer
    subversion/libsvn_subr/string.c:986: (apr_err=SVN_ERR_INCORRECT_PARAMS)
    svn: E200004: Number '888' is out of range '[0, 546]'

Daniel

P.S. In an earlier version of the patch I had some trouble getting an
apr_off_t to be printed in hex.  (The working answer: use the %qx
formatter and cast to unsigned long long.)  Constants such as
APR_OFF_T_FMT shouldn't include the "d" output modifier, only the "ll"
input modifier...

Reply via email to