On Mon, Jan 12, 2026 at 3:29 PM Branko Čibej <[email protected]> wrote:

> On 12. 1. 26 14:30, Timofei Zhakov wrote:
>
> On Mon, Jan 12, 2026 at 1:22 PM Branko Čibej <[email protected]> wrote:
>
>> On 12. 1. 26 12:52, [email protected] wrote:
>>
>> Author: brane
>> Date: Mon Jan 12 11:52:07 2026
>> New Revision: 1931262
>>
>> Log:
>> Fix warnings in the new checksum code.
>>
>> * subversion/libsvn_subr/checksum.c
>>   (svn_checksum): Remove unused variable.
>> * subversion/libsvn_subr/checksum_apr.c: Include <limits.h>.
>>   (svn_checksum__sha1, svn_checksum__sha1_ctx_update): Do not blindly cast
>>    or implicitly narrow the data length. Check the limits first.
>>
>> Modified:
>>    subversion/trunk/subversion/libsvn_subr/checksum.c
>>    subversion/trunk/subversion/libsvn_subr/checksum_apr.c
>>
>> Modified: subversion/trunk/subversion/libsvn_subr/checksum.c
>> ==============================================================================
>> --- subversion/trunk/subversion/libsvn_subr/checksum.c       Mon Jan 12 
>> 11:51:21 2026        (r1931261)
>> +++ subversion/trunk/subversion/libsvn_subr/checksum.c       Mon Jan 12 
>> 11:52:07 2026        (r1931262)
>> @@ -475,8 +475,6 @@ svn_checksum(svn_checksum_t **checksum,
>>               apr_size_t len,
>>               apr_pool_t *pool)
>>  {
>> -  apr_sha1_ctx_t sha1_ctx;
>> -
>>    SVN_ERR(validate_kind(kind));
>>    *checksum = svn_checksum_create(kind, pool);
>>
>>
>> Modified: subversion/trunk/subversion/libsvn_subr/checksum_apr.c
>> ==============================================================================
>> --- subversion/trunk/subversion/libsvn_subr/checksum_apr.c   Mon Jan 12 
>> 11:51:21 2026        (r1931261)
>> +++ subversion/trunk/subversion/libsvn_subr/checksum_apr.c   Mon Jan 12 
>> 11:52:07 2026        (r1931262)
>> @@ -21,6 +21,8 @@
>>   * ====================================================================
>>   */
>>
>> +#include <limits.h>
>> +
>>  #include "svn_private_config.h"
>>  #ifdef SVN_CHECKSUM_BACKEND_APR
>>
>> @@ -89,6 +91,10 @@ svn_checksum__sha1(unsigned char *digest
>>                     apr_size_t len)
>>  {
>>    apr_sha1_ctx_t sha1_ctx;
>> +
>> +  /* Do not blindly truncate the data length. */
>> +  SVN_ERR_ASSERT(len < UINT_MAX);
>> +
>>    apr_sha1_init(&sha1_ctx);
>>    apr_sha1_update(&sha1_ctx, data, (unsigned int)len);
>>    apr_sha1_final(digest, &sha1_ctx);
>> @@ -121,7 +127,9 @@ svn_checksum__sha1_ctx_update(svn_checks
>>                                const void *data,
>>                                apr_size_t len)
>>  {
>> -  apr_sha1_update(&ctx->apr_ctx, data, len);
>> +  /* Do not blindly truncate the data length. */
>> +  SVN_ERR_ASSERT(len < UINT_MAX);
>> +  apr_sha1_update(&ctx->apr_ctx, data, (unsigned int)len);
>>    return SVN_NO_ERROR;
>>  }
>>
>>
>> Just a quick note, it's generally not a good idea to use unchecked
>> typecasts anywhere. In this case there was a borderline chance of
>> Subversion quietly computing invalid hashes. The assert at least removes
>> the "quiet" part, although I suspect the better solution is to call
>> apr_sha1_update in UINT_MAX-sized chunks until all data are consumed.
>>
>
> I agree. It would be great if APR was accepting size as size_t. But it's
> not a big deal. Anyways, I'm pretty sure the issue existed there before.
>
> Maybe this function could feed it blocks of UINT_MAX if it exceeds the
> limit. But I don't think we should bother to support such edge cases,
> because if it happens, the issue is on the caller side -- it should not
> allocate 4GB buffers in memory.
>
>
>
> Is that a fact? Sorry but these days 4gigs is laughably small in certain
> applications. Our API promises "apr_size_t" chunks which on 64-bit
> platforms means larger than 4 GiB. We can change our API or we can fix the
> bug. It doesn't matter if the bug was there before, we know it's there now.
>
> -- Brane
>
>
Okay, it makes sense. I made a patch to support that behaviour. What do you
think?

[[[
Index: subversion/libsvn_subr/checksum_apr.c
===================================================================
--- subversion/libsvn_subr/checksum_apr.c (revision 1931267)
+++ subversion/libsvn_subr/checksum_apr.c (working copy)
@@ -91,12 +91,19 @@
                    apr_size_t len)
 {
   apr_sha1_ctx_t sha1_ctx;
+  const char *ptr = data;

-  /* Do not blindly truncate the data length. */
-  SVN_ERR_ASSERT(len < UINT_MAX);
+  apr_sha1_init(&sha1_ctx);

-  apr_sha1_init(&sha1_ctx);
-  apr_sha1_update(&sha1_ctx, data, (unsigned int)len);
+  while (len > 0)
+    {
+      unsigned int block = (len < UINT_MAX) ? (unsigned int)len
+                                            : UINT_MAX;
+      apr_sha1_update(&sha1_ctx, ptr, block);
+      len -= block;
+      ptr += block;
+    }
+
   apr_sha1_final(digest, &sha1_ctx);
   return SVN_NO_ERROR;
 }
@@ -127,9 +134,17 @@
                               const void *data,
                               apr_size_t len)
 {
-  /* Do not blindly truncate the data length. */
-  SVN_ERR_ASSERT(len < UINT_MAX);
-  apr_sha1_update(&ctx->apr_ctx, data, (unsigned int)len);
+  const char *ptr = data;
+
+  while (len > 0)
+    {
+      unsigned int block = (len < UINT_MAX) ? (unsigned int)len
+                                            : UINT_MAX;
+      apr_sha1_update(&ctx->apr_ctx, ptr, block);
+      len -= block;
+      ptr += block;
+    }
+
   return SVN_NO_ERROR;
 }
]]]

I don't really like casting 'void *' to 'char *' but it seems like the only
option.

I'm planning to do a similar thing to the bcrypt backend. A tiny note: long
is usually 32 bit even on 64 bit platforms (on Windows).

-- 
Timofei Zhakov
Index: subversion/libsvn_subr/checksum_apr.c
===================================================================
--- subversion/libsvn_subr/checksum_apr.c       (revision 1931267)
+++ subversion/libsvn_subr/checksum_apr.c       (working copy)
@@ -91,12 +91,19 @@
                    apr_size_t len)
 {
   apr_sha1_ctx_t sha1_ctx;
+  const char *ptr = data;
 
-  /* Do not blindly truncate the data length. */
-  SVN_ERR_ASSERT(len < UINT_MAX);
+  apr_sha1_init(&sha1_ctx);
 
-  apr_sha1_init(&sha1_ctx);
-  apr_sha1_update(&sha1_ctx, data, (unsigned int)len);
+  while (len > 0)
+    {
+      unsigned int block = (len < UINT_MAX) ? (unsigned int)len
+                                            : UINT_MAX;
+      apr_sha1_update(&sha1_ctx, ptr, block);
+      len -= block;
+      ptr += block;
+    }
+
   apr_sha1_final(digest, &sha1_ctx);
   return SVN_NO_ERROR;
 }
@@ -127,9 +134,17 @@
                               const void *data,
                               apr_size_t len)
 {
-  /* Do not blindly truncate the data length. */
-  SVN_ERR_ASSERT(len < UINT_MAX);
-  apr_sha1_update(&ctx->apr_ctx, data, (unsigned int)len);
+  const char *ptr = data;
+
+  while (len > 0)
+    {
+      unsigned int block = (len < UINT_MAX) ? (unsigned int)len
+                                            : UINT_MAX;
+      apr_sha1_update(&ctx->apr_ctx, ptr, block);
+      len -= block;
+      ptr += block;
+    }
+
   return SVN_NO_ERROR;
 }
 

Reply via email to