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