svn commit: r1931366 - in subversion/branches/1.14.x-r1931334: . build/ac-macros subversion/libsvn_subr subversion/tests/libsvn_subr

[email protected]
Newsgroups gmane.comp.version-control.subversion.svn
Message-ID <176857535260.2767734.2285007862407371284@svn02-us-east.apache.org>
Author: brane
Date: Fri Jan 16 14:55:52 2026
New Revision: 1931366

Log:
Cherry-picked r1931334 and r1931359 from trunk.

Added:
   subversion/branches/1.14.x-r1931334/subversion/tests/libsvn_subr/adler32-test.c
      - copied unchanged from r1931334, subversion/trunk/subversion/tests/libsvn_subr/adler32-test.c
Modified:
   subversion/branches/1.14.x-r1931334/   (props changed)
   subversion/branches/1.14.x-r1931334/build.conf
   subversion/branches/1.14.x-r1931334/build/ac-macros/zlib.m4
   subversion/branches/1.14.x-r1931334/subversion/libsvn_subr/adler32.c

Modified: subversion/branches/1.14.x-r1931334/build.conf
==============================================================================
--- subversion/branches/1.14.x-r1931334/build.conf	Fri Jan 16 14:47:12 2026	(r1931365)
+++ subversion/branches/1.14.x-r1931334/build.conf	Fri Jan 16 14:55:52 2026	(r1931366)
@@ -917,6 +917,14 @@ libs = libsvn_test libsvn_repos libsvn_f
 # ----------------------------------------------------------------------------
 # Tests for libsvn_subr
 
+[adler32-test]
+description = Test our implementation of the adler32 checksum.
+type = exe
+path = subversion/tests/libsvn_subr
+sources = adler32-test.c
+install = test
+libs = libsvn_test libsvn_subr apr
+
 [auth-test]
 description = Test platform-specific auth provider access
 type = exe

Modified: subversion/branches/1.14.x-r1931334/build/ac-macros/zlib.m4
==============================================================================
--- subversion/branches/1.14.x-r1931334/build/ac-macros/zlib.m4	Fri Jan 16 14:47:12 2026	(r1931365)
+++ subversion/branches/1.14.x-r1931334/build/ac-macros/zlib.m4	Fri Jan 16 14:55:52 2026	(r1931366)
@@ -73,11 +73,20 @@ AC_DEFUN(SVN_LIB_Z,
       ])
     fi
   fi
- 
+
   if test "$zlib_found" = "no"; then
     AC_MSG_ERROR([subversion requires zlib])
   fi
 
+  dnl Check if this zlib provides adler32_z().
+  save_ldflags="$LDFLAGS"
+  LDFLAGS="$SVN_ZLIB_LIBS"
+  AC_CHECK_FUNC([adler32_z],[
+    AC_DEFINE([SVN_ZLIB_HAS_ADLER32_Z],[1],
+              [Define if the function adler32_z() is available])
+  ],[])
+  LDFLAGS="$save_ldflags"
+
   AC_SUBST(SVN_ZLIB_INCLUDES)
   AC_SUBST(SVN_ZLIB_LIBS)
 ])

Modified: subversion/branches/1.14.x-r1931334/subversion/libsvn_subr/adler32.c
==============================================================================
--- subversion/branches/1.14.x-r1931334/subversion/libsvn_subr/adler32.c	Fri Jan 16 14:47:12 2026	(r1931365)
+++ subversion/branches/1.14.x-r1931334/subversion/libsvn_subr/adler32.c	Fri Jan 16 14:55:52 2026	(r1931366)
@@ -25,6 +25,7 @@
 #include <apr.h>
 #include <zlib.h>
 
+#include "svn_private_config.h"
 #include "private/svn_adler32.h"
 
 /**
@@ -34,12 +35,28 @@
  * still provides an extremely low probability of undetected errors"
  */
 
+/* Prefer adler32_z() over adler32(). It should be more efficient, especially
+ * if the length of the data is larger then the size of zlib's uInt. The
+ * current implementation of adler32() in zlib just calls adler32_z() anyway.
+ *
+ * adler32_z() was added in zlib 1.2.9.
+ */
+#if SVN_ZLIB_HAS_ADLER32_Z
+#define svn__adler32_impl adler32_z
+typedef z_size_t svn__adler32_size_t;
+#else
+typedef uInt svn__adler32_size_t;
+#define svn__adler32_impl adler32
+#endif
+#define SVN__ADLER32_SIZE_MAX (~(svn__adler32_size_t)0)
+#define svn__adler32_fn(c,d,s) svn__adler32_impl((c), (const Bytef *)(d), (s))
+
 /*
  * 65521 is the largest prime less than 65536.
  * "That 65521 is prime is important to avoid a possible large class of
  *  two-byte errors that leave the check unchanged."
  */
-#define ADLER_MOD_BASE 65521
+#define SVN__ADLER_MOD_BASE 65521U
 
 /*
  * Start with CHECKSUM and update the checksum by processing a chunk
@@ -48,6 +65,26 @@
 apr_uint32_t
 svn__adler32(apr_uint32_t checksum, const char *data, apr_off_t len)
 {
+  /* Process large amounts of data in max-sized chunks.
+   *
+   * Note: > not >=; then if sizeof(apr_off_t) <= sizeof(svn__adler32_size_t),
+   *                 this whole code block can be elided at compile time ...
+   */
+  if (SVN__PREDICT_FALSE(len > SVN__ADLER32_SIZE_MAX))
+    {
+      uLong partial = checksum; /* Avoid typecasts in the while loop. */
+      /* ... but >= here because we just might get lucky and
+       *     consume all the data in this loop.
+       */
+      while (len >= SVN__ADLER32_SIZE_MAX)
+        {
+          partial = svn__adler32_fn(partial, data, SVN__ADLER32_SIZE_MAX);
+          len -= SVN__ADLER32_SIZE_MAX;
+          data += SVN__ADLER32_SIZE_MAX;
+        }
+      checksum = (apr_uint32_t)partial;
+    }
+
   /* The actual limit can be set somewhat higher but should
    * not be lower because the SIMD code would not be used
    * in that case.
@@ -61,11 +98,10 @@ svn__adler32(apr_uint32_t checksum, cons
        * optimized code. Also, new zlib versions will come with
        * SIMD code for x86 and x64.
        */
-      return (apr_uint32_t)adler32(checksum,
-                                   (const Bytef *)data,
-                                   (uInt)len);
+      return (apr_uint32_t)svn__adler32_fn(checksum, data,
+                                           (svn__adler32_size_t)len);
     }
-  else
+  else if (len > 0)
     {
       const unsigned char *input = (const unsigned char *)data;
       apr_uint32_t s1 = checksum & 0xFFFF;
@@ -96,6 +132,8 @@ svn__adler32(apr_uint32_t checksum, cons
           s2 += s1;
         }
 
-      return ((s2 % ADLER_MOD_BASE) << 16) | (s1 % ADLER_MOD_BASE);
+      return ((s2 % SVN__ADLER_MOD_BASE) << 16) | (s1 % SVN__ADLER_MOD_BASE);
     }
+
+  return checksum;
 }

Copied: subversion/branches/1.14.x-r1931334/subversion/tests/libsvn_subr/adler32-test.c (from r1931334, subversion/trunk/subversion/tests/libsvn_subr/adler32-test.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ subversion/branches/1.14.x-r1931334/subversion/tests/libsvn_subr/adler32-test.c	Fri Jan 16 14:55:52 2026	(r1931366, copy of r1931334, subversion/trunk/subversion/tests/libsvn_subr/adler32-test.c)
@@ -0,0 +1,186 @@
+/*
+ * adler32-test.c:  tests the adler32 implementation.
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+#include <apr.h>
+#include <apr_pools.h>
+#include <apr_time.h>
+
+#include <zlib.h>
+
+#include "private/svn_adler32.h"
+#include "../svn_test.h"
+
+
+/* Allocate a buffer of size LEN from POOL and fill it with pseudo-random
+   data. In fact, the size of the buffer will be rounded up to the next
+   multiple of sizeof(apr_uint32_t). */
+static const char *make_random_data(apr_uint32_t *initial_seed,
+                                    apr_off_t len,
+                                    apr_pool_t *pool)
+{
+  const apr_off_t count = (len /  sizeof(apr_uint32_t)
+                           + (len %  sizeof(apr_uint32_t) ? 1 : 0));
+  apr_uint32_t *data = apr_palloc(pool, len * sizeof(*data));
+  apr_uint32_t seed = *initial_seed = (apr_uint32_t)apr_time_now();
+  apr_off_t i;
+
+  for (i = 0; i < count; ++i)
+    data[i] = svn_test_rand(&seed);
+
+  return (void*)data;
+}
+
+
+static const apr_off_t magic[8] = {
+  0, 1, 79, 80, 81, 5551, 5552, 5553
+};
+
+static const apr_off_t prime[300] = {
+  /* first 100 */
+  2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
+  67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
+  139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211,
+  223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
+  293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
+  383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
+  463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
+
+  /* 901st..1000th */
+  7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
+  7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
+  7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297,
+  7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411,
+  7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499,
+  7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
+  7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643,
+  7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
+  7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
+  7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
+
+  /* 9901st..9000th */
+  92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243,
+  92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363,
+  92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431,
+  92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567,
+  92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669,
+  92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753,
+  92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849,
+  92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951,
+  92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083,
+  93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179
+
+};
+
+static const apr_off_t power2[66] = {
+  /* There'll be some overlap with the not-quite-primes.
+     That's all right, we won't use the same data. */
+#define VALUES_FOR(n) ((n) - 1), (n), ((n) + 1)
+#define _64k (64 * 1024)
+  VALUES_FOR(2),         VALUES_FOR(4),         VALUES_FOR(8),
+  VALUES_FOR(16),        VALUES_FOR(32),        VALUES_FOR(64),
+  VALUES_FOR(128),       VALUES_FOR(256),       VALUES_FOR(512),
+  VALUES_FOR(_64k / 64), VALUES_FOR(_64k / 32), VALUES_FOR(_64k / 16),
+  VALUES_FOR(_64k / 8),  VALUES_FOR(_64k / 4),  VALUES_FOR(_64k / 2),
+  VALUES_FOR(_64k),      VALUES_FOR(_64k * 2),  VALUES_FOR(_64k * 4),
+  VALUES_FOR(_64k * 8),  VALUES_FOR(_64k * 16), VALUES_FOR(_64k * 32),
+  VALUES_FOR(_64k * 64)
+#undef _64k
+#undef VALUES_FOR
+};
+
+
+static svn_error_t *
+do_random_test(apr_uint32_t *seed,
+               const apr_off_t lengths[],
+               const apr_size_t array_size,
+               apr_pool_t *pool)
+{
+
+  const char *data = make_random_data(seed, lengths[array_size - 1], pool);
+  int i;
+
+  for (i = 0; i < array_size; ++i)
+    {
+      apr_uint32_t value_from_svn = svn__adler32(0, data, lengths[i]);
+      uLong value_from_zlib = adler32(0, (const Bytef*)data, (uInt)lengths[i]);
+      SVN_TEST_ASSERT(value_from_svn == value_from_zlib);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+test_random_magic(apr_pool_t *pool)
+{
+  apr_uint32_t seed;
+  svn_error_t *err = do_random_test(&seed, magic,
+                                    sizeof(magic) / sizeof(magic[0]),
+                                    pool);
+  if (err)
+    fprintf(stderr, "SEED: %lu\n", (unsigned long)seed);
+  return err;
+}
+
+static svn_error_t *
+test_random_prime(apr_pool_t *pool)
+{
+  apr_uint32_t seed;
+  svn_error_t *err = do_random_test(&seed, prime,
+                                    sizeof(prime) / sizeof(prime[0]),
+                                    pool);
+  if (err)
+    fprintf(stderr, "SEED: %lu\n", (unsigned long)seed);
+  return err;
+}
+
+static svn_error_t *
+test_random_power2(apr_pool_t *pool)
+{
+  apr_uint32_t seed;
+  svn_error_t *err = do_random_test(&seed, power2,
+                                    sizeof(power2) / sizeof(power2[0]),
+                                    pool);
+  if (err)
+    fprintf(stderr, "SEED: %lu\n", (unsigned long)seed);
+  return err;
+}
+
+
+/* An array of all test functions */
+
+static int max_threads = 4;
+
+static struct svn_test_descriptor_t test_funcs[] =
+  {
+    SVN_TEST_NULL,
+    SVN_TEST_PASS2(test_random_magic,
+                   "adler32 random with magic length"),
+    SVN_TEST_PASS2(test_random_prime,
+                   "adler32 random with prime length"),
+    SVN_TEST_PASS2(test_random_power2,
+                   "adler32 random with 2^n length"),
+    SVN_TEST_NULL
+  };
+
+SVN_TEST_MAIN
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.