Author: stefan2
Date: Sat Sep  6 20:54:40 2014
New Revision: 1622931

URL: http://svn.apache.org/r1622931
Log:
Harden FSFS's revision number parsing.  Replace the combination
of tokenizing and SVN_STR_TO_REV with a strict parsing function.

* subversion/libsvn_fs_fs/low_level.c
  (parse_revnum): New revnum parsing function.  It detects invalid
                  values, overflows and invalid terminators.
  (read_change,
   svn_fs_fs__parse_representation,
   svn_fs_fs__read_noderev,
   svn_fs_fs__read_rep_header): Use the new function to parse revnums.

Modified:
    subversion/trunk/subversion/libsvn_fs_fs/low_level.c

Modified: subversion/trunk/subversion/libsvn_fs_fs/low_level.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_fs/low_level.c?rev=1622931&r1=1622930&r2=1622931&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_fs/low_level.c (original)
+++ subversion/trunk/subversion/libsvn_fs_fs/low_level.c Sat Sep  6 20:54:40 
2014
@@ -69,6 +69,36 @@
  * various flags. */
 #define MAX_CHANGE_LINE_LEN FSFS_MAX_PATH_LEN + 256
 
+/* Convert the C string in *TEXT to a revision number and return it in *REV.
+ * Overflows, negative values other than -1 and terminating characters other
+ * than 0x20 or 0x0 will cause an error.  Set *TEXT to the first char after
+ * the initial separator or to EOS.
+ */
+static svn_error_t *
+parse_revnum(svn_revnum_t *rev,
+             const char **text)
+{
+  const char *string = *text;
+  if ((string[0] == '-') && (string[1] == '1'))
+    {
+      *rev = SVN_INVALID_REVNUM;
+      string += 2;
+    }
+  else
+    {
+      SVN_ERR(svn_revnum_parse(rev, string, &string));
+    }
+
+  if (*string == ' ')
+    ++string;
+  else if (*string != '\0')
+    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
+                            _("Invalid character in revision number"));
+
+  *text = string;
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_fs_fs__parse_revision_trailer(apr_off_t *root_offset,
                                   apr_off_t *changes_offset,
@@ -362,11 +392,7 @@ read_change(change_t **change_p,
   else
     {
       last_str = line->data;
-      str = svn_cstring_tokenize(" ", &last_str);
-      if (! str)
-        return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                                _("Invalid changes line in rev-file"));
-      info->copyfrom_rev = SVN_STR_TO_REV(str);
+      SVN_ERR(parse_revnum(&info->copyfrom_rev, (const char **)&last_str));
 
       if (! last_str)
         return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
@@ -649,12 +675,7 @@ svn_fs_fs__parse_representation(represen
   rep = apr_pcalloc(result_pool, sizeof(*rep));
   *rep_p = rep;
 
-  str = svn_cstring_tokenize(" ", &string);
-  if (str == NULL)
-    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
-                            _("Malformed text representation offset line in 
node-rev"));
-
-  rep->revision = SVN_STR_TO_REV(str);
+  SVN_ERR(parse_revnum(&rep->revision, (const char **)&string));
 
   /* initialize transaction info (never stored) */
   svn_fs_fs__id_txn_reset(&rep->txn_id);
@@ -865,15 +886,7 @@ svn_fs_fs__read_noderev(node_revision_t 
     }
   else
     {
-      char *str;
-
-      str = svn_cstring_tokenize(" ", &value);
-      if (str == NULL)
-        return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-                                 _("Malformed copyroot line in node-rev '%s'"),
-                                 noderev_id);
-
-      noderev->copyroot_rev = SVN_STR_TO_REV(str);
+      SVN_ERR(parse_revnum(&noderev->copyroot_rev, (const char **)&value));
 
       if (*value == '\0')
         return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
@@ -891,13 +904,7 @@ svn_fs_fs__read_noderev(node_revision_t 
     }
   else
     {
-      char *str = svn_cstring_tokenize(" ", &value);
-      if (str == NULL)
-        return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
-                                 _("Malformed copyfrom line in node-rev '%s'"),
-                                 noderev_id);
-
-      noderev->copyfrom_rev = SVN_STR_TO_REV(str);
+      SVN_ERR(parse_revnum(&noderev->copyfrom_rev, (const char **)&value));
 
       if (*value == 0)
         return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
@@ -1088,10 +1095,7 @@ svn_fs_fs__read_rep_header(svn_fs_fs__re
   if (! str || (strcmp(str, REP_DELTA) != 0))
     goto error;
 
-  str = svn_cstring_tokenize(" ", &last_str);
-  if (! str)
-    goto error;
-  (*header)->base_revision = SVN_STR_TO_REV(str);
+  SVN_ERR(parse_revnum(&(*header)->base_revision, (const char **)&last_str));
 
   str = svn_cstring_tokenize(" ", &last_str);
   if (! str)


Reply via email to