Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package aws-c-s3 for openSUSE:Factory 
checked in at 2026-04-09 16:12:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/aws-c-s3 (Old)
 and      /work/SRC/openSUSE:Factory/.aws-c-s3.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "aws-c-s3"

Thu Apr  9 16:12:04 2026 rev:37 rq:1345503 version:0.12.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/aws-c-s3/aws-c-s3.changes        2026-02-13 
16:39:51.427374598 +0100
+++ /work/SRC/openSUSE:Factory/.aws-c-s3.new.21863/aws-c-s3.changes     
2026-04-09 16:25:07.071433123 +0200
@@ -1,0 +2,8 @@
+Wed Mar 25 10:35:29 UTC 2026 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to version 0.12.0
+  * Auto - Update S3 Ruleset & Partition by @aws-crt-bot in (#613)
+  * Optimize the sizes of buffers requested from mem pool
+    by @DmitriyMusatkin in (#563)
+
+-------------------------------------------------------------------

Old:
----
  v0.11.5.tar.gz

New:
----
  v0.12.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ aws-c-s3.spec ++++++
--- /var/tmp/diff_new_pack.vS1Nhy/_old  2026-04-09 16:25:08.535493379 +0200
+++ /var/tmp/diff_new_pack.vS1Nhy/_new  2026-04-09 16:25:08.563494532 +0200
@@ -19,7 +19,7 @@
 %define library_version 1.0.0
 %define library_soversion 0unstable
 Name:           aws-c-s3
-Version:        0.11.5
+Version:        0.12.0
 Release:        0
 Summary:        AWS Cross-Platform, C99 wrapper for cryptography primitives
 License:        Apache-2.0

++++++ v0.11.5.tar.gz -> v0.12.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-s3-0.11.5/.github/workflows/ci.yml 
new/aws-c-s3-0.12.0/.github/workflows/ci.yml
--- old/aws-c-s3-0.11.5/.github/workflows/ci.yml        2026-01-13 
22:39:24.000000000 +0100
+++ new/aws-c-s3-0.12.0/.github/workflows/ci.yml        2026-03-23 
18:14:51.000000000 +0100
@@ -37,7 +37,7 @@
           - manylinux2014-x86
           - al2-x64
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -88,7 +88,7 @@
           # our base Linux image to Ubuntu 22.
             extra-build-flag: --cmake-extra=-DCMAKE_EXE_LINKER_FLAGS="-lresolv"
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -104,7 +104,7 @@
       matrix:
         sanitizers: [",thread", ",address,undefined"]
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -117,7 +117,7 @@
   linux-shared-libs:
     runs-on: ubuntu-24.04 # latest
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -130,7 +130,7 @@
   byo-crypto:
     runs-on: ubuntu-24.04 # latest
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -143,7 +143,7 @@
   windows:
     runs-on: windows-2025 # latest
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -159,7 +159,7 @@
       matrix:
         arch: [x86, x64]
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -171,7 +171,7 @@
   windows-shared-libs:
     runs-on: windows-2025 # latest
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -183,7 +183,7 @@
   windows-app-verifier:
     runs-on: windows-2025 # latest
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -198,7 +198,7 @@
   macos:
     runs-on: macos-14 # latest
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -215,7 +215,7 @@
   macos-x64:
     runs-on: macos-14-large # latest
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -234,7 +234,7 @@
   downstream:
     runs-on: ubuntu-24.04 # latest
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
@@ -247,7 +247,7 @@
   linux-debug:
     runs-on: ubuntu-24.04 # latest
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-s3-0.11.5/.github/workflows/codecov.yml 
new/aws-c-s3-0.12.0/.github/workflows/codecov.yml
--- old/aws-c-s3-0.11.5/.github/workflows/codecov.yml   2026-01-13 
22:39:24.000000000 +0100
+++ new/aws-c-s3-0.12.0/.github/workflows/codecov.yml   2026-03-23 
18:14:51.000000000 +0100
@@ -20,7 +20,7 @@
   codecov-linux:
     runs-on: ubuntu-24.04
     steps:
-    - uses: aws-actions/configure-aws-credentials@v4
+    - uses: aws-actions/configure-aws-credentials@v6
       with:
         role-to-assume: ${{ env.CRT_CI_ROLE }}
         aws-region: ${{ env.AWS_DEFAULT_REGION }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/aws-c-s3-0.11.5/include/aws/s3/private/s3_default_buffer_pool.h 
new/aws-c-s3-0.12.0/include/aws/s3/private/s3_default_buffer_pool.h
--- old/aws-c-s3-0.11.5/include/aws/s3/private/s3_default_buffer_pool.h 
2026-01-13 22:39:24.000000000 +0100
+++ new/aws-c-s3-0.12.0/include/aws/s3/private/s3_default_buffer_pool.h 
2026-03-23 18:14:51.000000000 +0100
@@ -44,6 +44,9 @@
     /* Max size of buffer to be allocated from primary. */
     size_t primary_cutoff;
 
+    /* Min size of buffer to be allocated from primary. */
+    size_t primary_min_cutoff;
+
     /* Overall memory allocated for blocks. */
     size_t primary_allocated;
     /* Number of blocks allocated in primary. */
@@ -91,6 +94,9 @@
     /* size at which allocations should go to secondary */
     size_t primary_size_cutoff;
 
+    /* size below which allocations should go to secondary */
+    size_t primary_size_min_cutoff;
+
     /* NOTE: See aws_s3_buffer_pool_usage_stats for descriptions of most 
fields */
 
     size_t mem_limit;
@@ -185,6 +191,18 @@
 AWS_S3_API struct aws_s3_default_buffer_pool_usage_stats 
aws_s3_default_buffer_pool_get_usage(
     struct aws_s3_buffer_pool *buffer_pool);
 
+enum aws_s3_default_buffer_pool_reserved_from {
+    AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY = 0,
+    AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY,
+    AWS_S3_BUFFER_POOL_RESERVED_FROM_SPECIAL,
+};
+
+/*
+ * Helper to determine which area of default buffer pool ticket was reserved 
from.
+ */
+AWS_S3_API enum aws_s3_default_buffer_pool_reserved_from 
aws_s3_default_buffer_pool_get_ticket_reserved_from(
+    struct aws_s3_default_buffer_ticket *ticket);
+
 /*
  * Trims all unused mem from the pool.
  * Warning: fairly slow operation, do not use in critical path.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-s3-0.11.5/include/aws/s3/private/s3_request.h 
new/aws-c-s3-0.12.0/include/aws/s3/private/s3_request.h
--- old/aws-c-s3-0.11.5/include/aws/s3/private/s3_request.h     2026-01-13 
22:39:24.000000000 +0100
+++ new/aws-c-s3-0.12.0/include/aws/s3/private/s3_request.h     2026-03-23 
18:14:51.000000000 +0100
@@ -240,10 +240,12 @@
      */
     struct aws_s3_buffer_ticket *ticket;
 
-    /* Beginning range of this part. */
+    /* Beginning range of this part.  */
     uint64_t part_range_start;
 
-    /* Last byte of this part.*/
+    /* Last byte of this part.
+     * Note: this is available on both put and get, but in put case it can be 
optimistic,
+     * ex for unknown content length we dont know what the end will be until 
we finish reading data. */
     uint64_t part_range_end;
 
     /* Part number that this request refers to.  If this is not a part, this 
can be 0.  (S3 Part Numbers start at 1.)
@@ -364,6 +366,11 @@
     uint32_t part_number,
     uint32_t flags);
 
+/* Gets the size of the part payload.
+ * Range is inclusive (i.e. 0-0 range has 1 byte size). In case of 
misconfigured range returns 0. */
+AWS_S3_API
+uint64_t aws_s3_request_get_payload_size(struct aws_s3_request *request);
+
 /* Set up the request to be sent. Called each time before the request is sent. 
Will initially call
  * aws_s3_request_clean_up_send_data to clear out anything previously existing 
in send_data. */
 AWS_S3_API
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-s3-0.11.5/source/s3_auto_ranged_get.c 
new/aws-c-s3-0.12.0/source/s3_auto_ranged_get.c
--- old/aws-c-s3-0.11.5/source/s3_auto_ranged_get.c     2026-01-13 
22:39:24.000000000 +0100
+++ new/aws-c-s3-0.12.0/source/s3_auto_ranged_get.c     2026-03-23 
18:14:51.000000000 +0100
@@ -265,6 +265,10 @@
                             1 /*part_number*/,
                             AWS_S3_REQUEST_FLAG_RECORD_RESPONSE_HEADERS |
                                 AWS_S3_REQUEST_FLAG_ALLOCATE_BUFFER_FROM_POOL);
+                        /* Note: our current default logic is to do part 1, 
discover size and then abort if payload its
+                         * too huge We optimistically reserve part size for it 
*/
+                        request->part_range_start = 0;
+                        request->part_range_end = meta_request->part_size - 1;
                         ++auto_ranged_get->synced_data.num_parts_requested;
 
                         break;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-s3-0.11.5/source/s3_auto_ranged_put.c 
new/aws-c-s3-0.12.0/source/s3_auto_ranged_put.c
--- old/aws-c-s3-0.11.5/source/s3_auto_ranged_put.c     2026-01-13 
22:39:24.000000000 +0100
+++ new/aws-c-s3-0.12.0/source/s3_auto_ranged_put.c     2026-03-23 
18:14:51.000000000 +0100
@@ -323,6 +323,36 @@
     .pause = s_s3_auto_ranged_put_pause,
 };
 
+/**
+ * Helper to initialize the request ranges and content-length
+ * based on the request->part_number and meta_request->part_size
+ */
+static int s_compute_request_body_size(const struct aws_s3_meta_request 
*meta_request, struct aws_s3_request *request) {
+    AWS_ERROR_PRECONDITION(meta_request);
+    AWS_ERROR_PRECONDITION(request);
+
+    const struct aws_s3_auto_ranged_put *auto_ranged_put = meta_request->impl;
+
+    size_t request_body_size = meta_request->part_size;
+    /* Last part--adjust size to match remaining content length. */
+    if (auto_ranged_put->has_content_length &&
+        request->part_number == 
auto_ranged_put->total_num_parts_from_content_length) {
+        size_t content_remainder = (size_t)(auto_ranged_put->content_length % 
(uint64_t)meta_request->part_size);
+
+        if (content_remainder > 0) {
+            request_body_size = content_remainder;
+        }
+    }
+    if (aws_mul_u64_checked(request->part_number - 1, meta_request->part_size, 
&request->part_range_start)) {
+        return AWS_OP_ERR;
+    }
+    if (aws_add_u64_checked(request->part_range_start, request_body_size - 1, 
&request->part_range_end)) {
+        return AWS_OP_ERR;
+    }
+    request->content_length = request_body_size;
+    return AWS_OP_SUCCESS;
+}
+
 /* Allocate a new auto-ranged put meta request */
 struct aws_s3_meta_request *aws_s3_meta_request_auto_ranged_put_new(
     struct aws_allocator *allocator,
@@ -605,6 +635,8 @@
 
                 request->part_number = 
auto_ranged_put->threaded_update_data.next_part_number;
 
+                s_compute_request_body_size(meta_request, request);
+
                 /* If request was previously uploaded, we prepare it to ensure 
checksums still match,
                  * but ultimately it gets marked no-op and we don't send it */
                 request->was_previously_uploaded = request_previously_uploaded;
@@ -761,36 +793,6 @@
     return work_remaining;
 }
 
-/**
- * Helper to initialize the request ranges and content-length
- * based on the request->part_number and meta_request->part_size
- */
-static int s_compute_request_body_size(const struct aws_s3_meta_request 
*meta_request, struct aws_s3_request *request) {
-    AWS_ERROR_PRECONDITION(meta_request);
-    AWS_ERROR_PRECONDITION(request);
-
-    const struct aws_s3_auto_ranged_put *auto_ranged_put = meta_request->impl;
-
-    size_t request_body_size = meta_request->part_size;
-    /* Last part--adjust size to match remaining content length. */
-    if (auto_ranged_put->has_content_length &&
-        request->part_number == 
auto_ranged_put->total_num_parts_from_content_length) {
-        size_t content_remainder = (size_t)(auto_ranged_put->content_length % 
(uint64_t)meta_request->part_size);
-
-        if (content_remainder > 0) {
-            request_body_size = content_remainder;
-        }
-    }
-    if (aws_mul_u64_checked(request->part_number - 1, meta_request->part_size, 
&request->part_range_start)) {
-        return AWS_OP_ERR;
-    }
-    if (aws_add_u64_checked(request->part_range_start, request_body_size - 1, 
&request->part_range_end)) {
-        return AWS_OP_ERR;
-    }
-    request->content_length = request_body_size;
-    return AWS_OP_SUCCESS;
-}
-
 static int s_verify_part_matches_checksum(
     struct aws_allocator *allocator,
     struct aws_byte_cursor body_cur,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-s3-0.11.5/source/s3_client.c 
new/aws-c-s3-0.12.0/source/s3_client.c
--- old/aws-c-s3-0.11.5/source/s3_client.c      2026-01-13 22:39:24.000000000 
+0100
+++ new/aws-c-s3-0.12.0/source/s3_client.c      2026-03-23 18:14:51.000000000 
+0100
@@ -11,6 +11,7 @@
 #include "aws/s3/private/s3_default_meta_request.h"
 #include "aws/s3/private/s3_meta_request_impl.h"
 #include "aws/s3/private/s3_parallel_input_stream.h"
+#include "aws/s3/private/s3_request.h"
 #include "aws/s3/private/s3_request_messages.h"
 #include "aws/s3/private/s3_util.h"
 #include "aws/s3/private/s3express_credentials_provider_impl.h"
@@ -2059,7 +2060,10 @@
     aws_s3_meta_request_prepare_request_callback_fn *callback,
     void *user_data) {
 
-    if (request->ticket == NULL && request->should_allocate_buffer_from_pool) {
+    size_t request_size = (size_t)aws_s3_request_get_payload_size(request);
+    AWS_ASSERT(request_size != 0); /* Note: 0 request size is invalid in all 
cases. */
+
+    if (request->ticket == NULL && request->should_allocate_buffer_from_pool 
&& request_size > 0) {
 
         if (request->send_data.metrics) {
             struct aws_s3_request_metrics *metric = request->send_data.metrics;
@@ -2069,10 +2073,11 @@
 
         struct aws_allocator *allocator = request->allocator;
         struct aws_s3_meta_request *meta_request = request->meta_request;
+
         struct aws_s3_buffer_pool_reserve_meta meta = {
             .client = client,
             .meta_request = meta_request,
-            .size = request->buffer_size,
+            .size = request_size,
         };
 
         struct aws_s3_reserve_memory_payload *payload =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-s3-0.11.5/source/s3_default_buffer_pool.c 
new/aws-c-s3-0.12.0/source/s3_default_buffer_pool.c
--- old/aws-c-s3-0.11.5/source/s3_default_buffer_pool.c 2026-01-13 
22:39:24.000000000 +0100
+++ new/aws-c-s3-0.12.0/source/s3_default_buffer_pool.c 2026-03-23 
18:14:51.000000000 +0100
@@ -51,7 +51,7 @@
     size_t chunks_used;
     bool forced;
     struct aws_s3_buffer_pool *pool;
-    bool is_special_block; /* True if this ticket is from a special-sized 
block */
+    enum aws_s3_default_buffer_pool_reserved_from reserved_from; /* which area 
ticket was reserved from */
 };
 
 /* Default size for blocks array. Note: this is just for meta info, blocks
@@ -83,6 +83,12 @@
 static const size_t 
s_max_impact_of_forced_buffers_on_memory_limit_as_percentage = 80;
 
 /*
+ * primary min cut off. below this number buffers are not allocated from 
primary and instead use
+ * secondary.
+ */
+static const size_t s_primary_min_cutoff = KB_TO_BYTES(512);
+
+/*
  * Sets n bits at position starting with LSB.
  * Note: n must be at most 8, but in practice will always be at most 4.
  * position + n should at most be 16
@@ -232,6 +238,20 @@
         chunk_size = 0;
     }
 
+    /*
+     * Determine the min cutoff. At high level this tries to avoid using 
buffer pool if requests
+     * are small compared to primary (ex. 512 req buffer compared to 8mb 
buffer size).
+     * How that is done is fairly arbitrary. System allocator tends to be a 
bit better on tiny allocations.
+     * And we want to avoid wasting mem in that case.
+     * Note this is not the answer for wasting mem, but it does improve some 
corner cases.
+     */
+    size_t min_primary_size = 0;
+    if (4 * chunk_size >= s_primary_min_cutoff) {
+        min_primary_size = s_primary_min_cutoff;
+    } else {
+        min_primary_size = 0;
+    }
+
     size_t page_size = aws_system_info_page_size();
     /* TODO: if people override their allocator, this will not wrap their 
allocator at all. eg: mem-tracing allocator
      * will be ignored. */
@@ -248,6 +268,7 @@
      * Tries to balance between how many allocations use buffer and buffer 
space
      * being wasted. */
     buffer_pool->primary_size_cutoff = chunk_size * 4;
+    buffer_pool->primary_size_min_cutoff = min_primary_size;
     buffer_pool->mem_limit = adjusted_mem_lim;
 
     int mutex_error = aws_mutex_init(&buffer_pool->mutex);
@@ -395,16 +416,22 @@
 
         if (ticket->ptr == NULL) {
             /* Ticket was never used, make sure to clean up reserved count. */
-            if (ticket->is_special_block) {
-                buffer_pool->special_blocks_reserved -= ticket->size;
-            } else if (ticket->size <= buffer_pool->primary_size_cutoff) {
-                buffer_pool->primary_reserved -= ticket->size;
-            } else {
-                buffer_pool->secondary_reserved -= ticket->size;
+            switch (ticket->reserved_from) {
+                case AWS_S3_BUFFER_POOL_RESERVED_FROM_SPECIAL:
+                    buffer_pool->special_blocks_reserved -= ticket->size;
+                    break;
+                case AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY:
+                    buffer_pool->primary_reserved -= ticket->size;
+                    break;
+                case AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY:
+                    buffer_pool->secondary_reserved -= ticket->size;
+                    break;
+                default:
+                    AWS_ASSERT(false); /* someone forgot to update this after 
adding new member. */
             }
         } else {
             /* Handle special block returns */
-            if (ticket->is_special_block) {
+            if (ticket->reserved_from == 
AWS_S3_BUFFER_POOL_RESERVED_FROM_SPECIAL) {
                 struct aws_hash_element *elem = NULL;
                 aws_hash_table_find(&buffer_pool->special_blocks, (void 
*)ticket->size, &elem);
                 /* TODO: the lifetime between the ticket and the special 
block, let's assume the block will always be
@@ -427,7 +454,7 @@
                 /* Make sure we do find where the ticket buffer from the list. 
*/
                 AWS_FATAL_ASSERT(found);
                 buffer_pool->special_blocks_used -= ticket->size;
-            } else if (ticket->size <= buffer_pool->primary_size_cutoff) {
+            } else if (ticket->reserved_from == 
AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY) {
 
                 size_t chunks_used = ticket->size / buffer_pool->chunk_size;
                 if (ticket->size % buffer_pool->chunk_size != 0) {
@@ -455,13 +482,15 @@
                 if (ticket->forced) {
                     buffer_pool->forced_used -= ticket->size;
                 }
-            } else {
+            } else if (ticket->reserved_from == 
AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY) {
                 aws_mem_release(buffer_pool->base_allocator, ticket->ptr);
                 buffer_pool->secondary_used -= ticket->size;
 
                 if (ticket->forced) {
                     buffer_pool->forced_used -= ticket->size;
                 }
+            } else {
+                AWS_ASSERT(false); /* someone forgot to update this after 
adding new member. */
             }
         }
         aws_mem_release(buffer_pool->base_allocator, ticket);
@@ -608,11 +637,29 @@
 
         /* Check if this is a special-sized allocation */
         if (from_special) {
-            ticket->is_special_block = true;
+            ticket->reserved_from = AWS_S3_BUFFER_POOL_RESERVED_FROM_SPECIAL;
             buffer_pool->special_blocks_reserved += meta.size;
         } else if (meta.size <= buffer_pool->primary_size_cutoff) {
-            buffer_pool->primary_reserved += meta.size;
+            /* This needs to be smarter. Currently if primary req size is 
below limit, it will allocate full block,
+                which can be above limit. */
+            if (meta.size <= buffer_pool->primary_size_min_cutoff) {
+                ticket->reserved_from = 
AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY;
+                buffer_pool->secondary_reserved += meta.size;
+            } else {
+                if ((buffer_pool->primary_used + buffer_pool->primary_reserved 
+ meta.size) >
+                        buffer_pool->primary_allocated &&
+                    (overall_taken + buffer_pool->block_size) > 
buffer_pool->mem_limit) {
+                    /* allocating this from primary would result in exceeding 
mem limit if new block is created,
+                        so allocate from secondary instead. */
+                    ticket->reserved_from = 
AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY;
+                    buffer_pool->secondary_reserved += meta.size;
+                } else {
+                    ticket->reserved_from = 
AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY;
+                    buffer_pool->primary_reserved += meta.size;
+                }
+            }
         } else {
+            ticket->reserved_from = AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY;
             buffer_pool->secondary_reserved += meta.size;
         }
     }
@@ -639,6 +686,12 @@
         ticket->forced = true;
         ticket->pool = buffer_pool_wrapper;
 
+        if (meta.size <= buffer_pool->primary_size_cutoff && meta.size >= 
buffer_pool->primary_size_min_cutoff) {
+            ticket->reserved_from = AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY;
+        } else {
+            ticket->reserved_from = AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY;
+        }
+
     } else {
         ticket = s_try_reserve_synced(buffer_pool_wrapper, meta);
     }
@@ -684,6 +737,7 @@
             if (!s_check_bits(block->alloc_bit_mask, chunk_i, chunks_needed)) {
                 alloc_ptr = block->block_ptr + chunk_i * 
buffer_pool->chunk_size;
                 block->alloc_bit_mask = s_set_bits(block->alloc_bit_mask, 
chunk_i, chunks_needed);
+                AWS_LOGF_INFO(AWS_LS_S3_CLIENT, "Reusing existing primary 
block %zu", i);
                 goto on_allocated;
             }
         }
@@ -697,6 +751,12 @@
     aws_array_list_push_back(&buffer_pool->blocks, &block);
     alloc_ptr = block.block_ptr;
 
+    AWS_LOGF_INFO(
+        AWS_LS_S3_CLIENT,
+        "Allocated primary block: size=%zu, total_allocated=%zu",
+        buffer_pool->block_size,
+        buffer_pool->primary_allocated);
+
     buffer_pool->primary_allocated += buffer_pool->block_size;
 
 on_allocated:
@@ -741,13 +801,10 @@
     AWS_PRECONDITION(ticket->ptr == NULL);
 
     AWS_LOGF_INFO(
-        AWS_LS_S3_CLIENT,
-        "s_acquire_buffer_synced: size=%zu, is_special_block=%d",
-        ticket->size,
-        ticket->is_special_block);
+        AWS_LS_S3_CLIENT, "s_acquire_buffer_synced: size=%zu, 
reserved_from=%u", ticket->size, ticket->reserved_from);
 
     /* Check if this is a special-sized allocation */
-    if (ticket->is_special_block) {
+    if (ticket->reserved_from == AWS_S3_BUFFER_POOL_RESERVED_FROM_SPECIAL) {
         struct aws_hash_element *elem = NULL;
         aws_hash_table_find(&buffer_pool->special_blocks, (void 
*)ticket->size, &elem);
         AWS_FATAL_ASSERT(elem != NULL);
@@ -761,13 +818,13 @@
         for (size_t i = 0; i < aws_array_list_length(&special_list->blocks); 
++i) {
             struct s3_buffer_pool_block *block;
             aws_array_list_get_at_ptr(&special_list->blocks, (void **)&block, 
i);
-            AWS_LOGF_INFO(AWS_LS_S3_CLIENT, "Checking block %zu: 
alloc_bit_mask=%u", i, block->alloc_bit_mask);
+            AWS_LOGF_INFO(AWS_LS_S3_CLIENT, "Checking special block %zu: 
alloc_bit_mask=%u", i, block->alloc_bit_mask);
             /* Try to find if any block in the list is not used. */
             if (block->alloc_bit_mask == 0) {
                 block->alloc_bit_mask = UINT16_MAX;
                 ticket->ptr = block->block_ptr;
                 AWS_ASSERT(ticket->size == block->block_size);
-                AWS_LOGF_INFO(AWS_LS_S3_CLIENT, "Reusing existing block %zu", 
i);
+                AWS_LOGF_INFO(AWS_LS_S3_CLIENT, "Reusing existing special 
block %zu", i);
                 break;
             }
         }
@@ -788,9 +845,10 @@
         }
         buffer_pool->special_blocks_used += ticket->size;
         buffer_pool->special_blocks_reserved -= ticket->size;
-    } else if (ticket->size <= buffer_pool->primary_size_cutoff) {
+    } else if (ticket->reserved_from == 
AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY) {
         ticket->ptr = s_primary_acquire_synced(buffer_pool, ticket);
     } else {
+        AWS_ASSERT(ticket->reserved_from == 
AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY);
         ticket->ptr = aws_mem_acquire(buffer_pool->base_allocator, 
ticket->size);
         buffer_pool->secondary_used += ticket->size;
 
@@ -816,6 +874,7 @@
     struct aws_s3_default_buffer_pool_usage_stats ret = (struct 
aws_s3_default_buffer_pool_usage_stats){
         .mem_limit = buffer_pool->mem_limit,
         .primary_cutoff = buffer_pool->primary_size_cutoff,
+        .primary_min_cutoff = buffer_pool->primary_size_min_cutoff,
         .primary_allocated = buffer_pool->primary_allocated,
         .primary_used = buffer_pool->primary_used,
         .primary_reserved = buffer_pool->primary_reserved,
@@ -916,3 +975,9 @@
     /* Return the aligned size */
     return chunks_needed * buffer_pool->chunk_size;
 }
+
+enum aws_s3_default_buffer_pool_reserved_from 
aws_s3_default_buffer_pool_get_ticket_reserved_from(
+    struct aws_s3_default_buffer_ticket *ticket) {
+    AWS_FATAL_ASSERT(ticket);
+    return ticket->reserved_from;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/aws-c-s3-0.11.5/source/s3_endpoint_resolver/aws_s3_endpoint_resolver_partition.c
 
new/aws-c-s3-0.12.0/source/s3_endpoint_resolver/aws_s3_endpoint_resolver_partition.c
--- 
old/aws-c-s3-0.11.5/source/s3_endpoint_resolver/aws_s3_endpoint_resolver_partition.c
        2026-01-13 22:39:24.000000000 +0100
+++ 
new/aws-c-s3-0.12.0/source/s3_endpoint_resolver/aws_s3_endpoint_resolver_partition.c
        2026-03-23 18:14:51.000000000 +0100
@@ -151,112 +151,114 @@
        'e', 'u', 's', 'c', '\\', '\\', '-', '(', 'd', 'e', ')', '\\', '\\', 
'-', '\\', '\\', 'w', '+', '\\', '\\',
        '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 
'n', 's', '"', ':', '{', '"',
        'e', 'u', 's', 'c', '-', 'd', 'e', '-', 'e', 'a', 's', 't', '-', '1', 
'"', ':', '{', '"', 'd', 'e',
-       's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'E', 'U', ' 
', '(', 'G', 'e', 'r', 'm',
-       'a', 'n', 'y', ')', '"', '}', '}', '}', ',', '{', '"', 'i', 'd', '"', 
':', '"', 'a', 'w', 's', '-',
-       'i', 's', 'o', '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', '"', 
':', '{', '"', 'd', 'n', 's',
-       'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'c', '2', 's', '.', 'i', 
'c', '.', 'g', 'o', 'v', '"',
-       ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', 
'S', 'u', 'f', 'f', 'i', 'x',
-       '"', ':', '"', 'a', 'p', 'i', '.', 'a', 'w', 's', '.', 'i', 'c', '.', 
'g', 'o', 'v', '"', ',', '"',
-       'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 
'R', 'e', 'g', 'i', 'o', 'n',
-       '"', ':', '"', 'u', 's', '-', 'i', 's', 'o', '-', 'e', 'a', 's', 't', 
'-', '1', '"', ',', '"', 'n',
-       'a', 'm', 'e', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '"', 
',', '"', 's', 'u', 'p', 'p',
-       'o', 'r', 't', 's', 'D', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', '"', 
':', 't', 'r', 'u', 'e', ',',
-       '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'F', 'I', 'P', 'S', '"', 
':', 't', 'r', 'u', 'e', '}',
-       ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', '"', 
':', '"', '^', 'u', 's', '\\',
-       '\\', '-', 'i', 's', 'o', '\\', '\\', '-', '\\', '\\', 'w', '+', '\\', 
'\\', '-', '\\', '\\', 'd', '+', '$',
-       '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 's', '"', ':', '{', '"', 
'a', 'w', 's', '-', 'i', 's',
-       'o', '-', 'g', 'l', 'o', 'b', 'a', 'l', '"', ':', '{', '"', 'd', 'e', 
's', 'c', 'r', 'i', 'p', 't',
-       'i', 'o', 'n', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', ' ', 
'g', 'l', 'o', 'b', 'a', 'l',
-       ' ', 'r', 'e', 'g', 'i', 'o', 'n', '"', '}', ',', '"', 'u', 's', '-', 
'i', 's', 'o', '-', 'e', 'a',
-       's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 
'p', 't', 'i', 'o', 'n', '"',
-       ':', '"', 'U', 'S', ' ', 'I', 'S', 'O', ' ', 'E', 'a', 's', 't', '"', 
'}', ',', '"', 'u', 's', '-',
-       'i', 's', 'o', '-', 'w', 'e', 's', 't', '-', '1', '"', ':', '{', '"', 
'd', 'e', 's', 'c', 'r', 'i',
-       'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'I', 'S', 'O', ' 
', 'W', 'E', 'S', 'T', '"',
-       '}', '}', '}', ',', '{', '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', 
'-', 'i', 's', 'o', '-', 'b',
-       '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', '"', ':', '{', '"', 
'd', 'n', 's', 'S', 'u', 'f',
-       'f', 'i', 'x', '"', ':', '"', 's', 'c', '2', 's', '.', 's', 'g', 'o', 
'v', '.', 'g', 'o', 'v', '"',
-       ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', 
'S', 'u', 'f', 'f', 'i', 'x',
-       '"', ':', '"', 'a', 'p', 'i', '.', 'a', 'w', 's', '.', 's', 'c', 'l', 
'o', 'u', 'd', '"', ',', '"',
-       'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 
'R', 'e', 'g', 'i', 'o', 'n',
-       '"', ':', '"', 'u', 's', '-', 'i', 's', 'o', 'b', '-', 'e', 'a', 's', 
't', '-', '1', '"', ',', '"',
-       'n', 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', 
'-', 'b', '"', ',', '"', 's',
-       'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 'u', 'a', 'l', 'S', 't', 'a', 
'c', 'k', '"', ':', 't', 'r',
-       'u', 'e', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'F', 'I', 
'P', 'S', '"', ':', 't', 'r',
-       'u', 'e', '}', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', 'g', 
'e', 'x', '"', ':', '"', '^',
-       'u', 's', '\\', '\\', '-', 'i', 's', 'o', 'b', '\\', '\\', '-', '\\', 
'\\', 'w', '+', '\\', '\\', '-', '\\',
-       '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 's', 
'"', ':', '{', '"', 'a', 'w',
-       's', '-', 'i', 's', 'o', '-', 'b', '-', 'g', 'l', 'o', 'b', 'a', 'l', 
'"', ':', '{', '"', 'd', 'e',
-       's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'a', 'w', 
's', '-', 'i', 's', 'o', '-',
-       'b', ' ', 'g', 'l', 'o', 'b', 'a', 'l', ' ', 'r', 'e', 'g', 'i', 'o', 
'n', '"', '}', ',', '"', 'u',
-       's', '-', 'i', 's', 'o', 'b', '-', 'e', 'a', 's', 't', '-', '1', '"', 
':', '{', '"', 'd', 'e', 's',
-       'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 
'I', 'S', 'O', 'B', ' ', 'E',
-       'a', 's', 't', ' ', '(', 'O', 'h', 'i', 'o', ')', '"', '}', ',', '"', 
'u', 's', '-', 'i', 's', 'o',
-       'b', '-', 'w', 'e', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 
's', 'c', 'r', 'i', 'p', 't',
-       'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'I', 'S', 'O', 'B', ' ', 
'W', 'e', 's', 't', '"', '}',
-       '}', '}', ',', '{', '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', '-', 
'i', 's', 'o', '-', 'e', '"',
-       ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', '"', ':', '{', '"', 'd', 
'n', 's', 'S', 'u', 'f', 'f',
-       'i', 'x', '"', ':', '"', 'c', 'l', 'o', 'u', 'd', '.', 'a', 'd', 'c', 
'-', 'e', '.', 'u', 'k', '"',
-       ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', 
'S', 'u', 'f', 'f', 'i', 'x',
-       '"', ':', '"', 'a', 'p', 'i', '.', 'c', 'l', 'o', 'u', 'd', '-', 'a', 
'w', 's', '.', 'a', 'd', 'c',
-       '-', 'e', '.', 'u', 'k', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', 
'i', 't', 'G', 'l', 'o', 'b',
-       'a', 'l', 'R', 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'e', 'u', '-', 
'i', 's', 'o', 'e', '-', 'w',
-       'e', 's', 't', '-', '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', 
'"', 'a', 'w', 's', '-', 'i',
-       's', 'o', '-', 'e', '"', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 
's', 'D', 'u', 'a', 'l', 'S',
-       't', 'a', 'c', 'k', '"', ':', 't', 'r', 'u', 'e', ',', '"', 's', 'u', 
'p', 'p', 'o', 'r', 't', 's',
-       'F', 'I', 'P', 'S', '"', ':', 't', 'r', 'u', 'e', '}', ',', '"', 'r', 
'e', 'g', 'i', 'o', 'n', 'R',
-       'e', 'g', 'e', 'x', '"', ':', '"', '^', 'e', 'u', '\\', '\\', '-', 'i', 
's', 'o', 'e', '\\', '\\', '-',
-       '\\', '\\', 'w', '+', '\\', '\\', '-', '\\', '\\', 'd', '+', '$', '"', 
',', '"', 'r', 'e', 'g', 'i', 'o',
-       'n', 's', '"', ':', '{', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 
'e', '-', 'g', 'l', 'o', 'b',
-       'a', 'l', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 
'i', 'o', 'n', '"', ':', '"',
-       'a', 'w', 's', '-', 'i', 's', 'o', '-', 'e', ' ', 'g', 'l', 'o', 'b', 
'a', 'l', ' ', 'r', 'e', 'g',
-       'i', 'o', 'n', '"', '}', ',', '"', 'e', 'u', '-', 'i', 's', 'o', 'e', 
'-', 'w', 'e', 's', 't', '-',
-       '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 
'o', 'n', '"', ':', '"', 'E',
-       'U', ' ', 'I', 'S', 'O', 'E', ' ', 'W', 'e', 's', 't', '"', '}', '}', 
'}', ',', '{', '"', 'i', 'd',
-       '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'f', '"', ',', 
'"', 'o', 'u', 't', 'p', 'u',
-       't', 's', '"', ':', '{', '"', 'd', 'n', 's', 'S', 'u', 'f', 'f', 'i', 
'x', '"', ':', '"', 'c', 's',
-       'p', '.', 'h', 'c', 'i', '.', 'i', 'c', '.', 'g', 'o', 'v', '"', ',', 
'"', 'd', 'u', 'a', 'l', 'S',
-       't', 'a', 'c', 'k', 'D', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', 
':', '"', 'a', 'p', 'i', '.',
-       'a', 'w', 's', '.', 'h', 'c', 'i', '.', 'i', 'c', '.', 'g', 'o', 'v', 
'"', ',', '"', 'i', 'm', 'p',
-       'l', 'i', 'c', 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 'R', 'e', 'g', 
'i', 'o', 'n', '"', ':', '"',
-       'u', 's', '-', 'i', 's', 'o', 'f', '-', 's', 'o', 'u', 't', 'h', '-', 
'1', '"', ',', '"', 'n', 'a',
-       'm', 'e', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'f', 
'"', ',', '"', 's', 'u', 'p',
-       'p', 'o', 'r', 't', 's', 'D', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 
'"', ':', 't', 'r', 'u', 'e',
-       ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'F', 'I', 'P', 'S', 
'"', ':', 't', 'r', 'u', 'e',
-       '}', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', 
'"', ':', '"', '^', 'u', 's',
-       '\\', '\\', '-', 'i', 's', 'o', 'f', '\\', '\\', '-', '\\', '\\', 'w', 
'+', '\\', '\\', '-', '\\', '\\', 'd',
-       '+', '$', '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 's', '"', ':', 
'{', '"', 'a', 'w', 's', '-',
-       'i', 's', 'o', '-', 'f', '-', 'g', 'l', 'o', 'b', 'a', 'l', '"', ':', 
'{', '"', 'd', 'e', 's', 'c',
-       'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'a', 'w', 's', '-', 
'i', 's', 'o', '-', 'f', ' ',
+       's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'A', 'W', 
'S', ' ', 'E', 'u', 'r', 'o',
+       'p', 'e', 'a', 'n', ' ', 'S', 'o', 'v', 'e', 'r', 'e', 'i', 'g', 'n', ' 
', 'C', 'l', 'o', 'u', 'd',
+       ' ', '(', 'G', 'e', 'r', 'm', 'a', 'n', 'y', ')', '"', '}', '}', '}', 
',', '{', '"', 'i', 'd', '"',
+       ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '"', ',', '"', 'o', 'u', 
't', 'p', 'u', 't', 's', '"',
+       ':', '{', '"', 'd', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', 
'"', 'c', '2', 's', '.', 'i',
+       'c', '.', 'g', 'o', 'v', '"', ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 
'a', 'c', 'k', 'D', 'n', 's',
+       'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'a', 'p', 'i', '.', 'a', 
'w', 's', '.', 'i', 'c', '.',
+       'g', 'o', 'v', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 
'G', 'l', 'o', 'b', 'a', 'l',
+       'R', 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'u', 's', '-', 'i', 's', 
'o', '-', 'e', 'a', 's', 't',
+       '-', '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 
's', '-', 'i', 's', 'o', '"',
+       ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 'u', 'a', 'l', 
'S', 't', 'a', 'c', 'k', '"',
+       ':', 't', 'r', 'u', 'e', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 
's', 'F', 'I', 'P', 'S', '"',
+       ':', 't', 'r', 'u', 'e', '}', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 
'R', 'e', 'g', 'e', 'x', '"',
+       ':', '"', '^', 'u', 's', '\\', '\\', '-', 'i', 's', 'o', '\\', '\\', 
'-', '\\', '\\', 'w', '+', '\\', '\\',
+       '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 
'n', 's', '"', ':', '{', '"',
+       'a', 'w', 's', '-', 'i', 's', 'o', '-', 'g', 'l', 'o', 'b', 'a', 'l', 
'"', ':', '{', '"', 'd', 'e',
+       's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'a', 'w', 
's', '-', 'i', 's', 'o', ' ',
        'g', 'l', 'o', 'b', 'a', 'l', ' ', 'r', 'e', 'g', 'i', 'o', 'n', '"', 
'}', ',', '"', 'u', 's', '-',
-       'i', 's', 'o', 'f', '-', 'e', 'a', 's', 't', '-', '1', '"', ':', '{', 
'"', 'd', 'e', 's', 'c', 'r',
-       'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'I', 'S', 
'O', 'F', ' ', 'E', 'A', 'S',
-       'T', '"', '}', ',', '"', 'u', 's', '-', 'i', 's', 'o', 'f', '-', 's', 
'o', 'u', 't', 'h', '-', '1',
-       '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 
'n', '"', ':', '"', 'U', 'S',
-       ' ', 'I', 'S', 'O', 'F', ' ', 'S', 'O', 'U', 'T', 'H', '"', '}', '}', 
'}', ',', '{', '"', 'i', 'd',
-       '"', ':', '"', 'a', 'w', 's', '-', 'u', 's', '-', 'g', 'o', 'v', '"', 
',', '"', 'o', 'u', 't', 'p',
-       'u', 't', 's', '"', ':', '{', '"', 'd', 'n', 's', 'S', 'u', 'f', 'f', 
'i', 'x', '"', ':', '"', 'a',
-       'm', 'a', 'z', 'o', 'n', 'a', 'w', 's', '.', 'c', 'o', 'm', '"', ',', 
'"', 'd', 'u', 'a', 'l', 'S',
-       't', 'a', 'c', 'k', 'D', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', 
':', '"', 'a', 'p', 'i', '.',
-       'a', 'w', 's', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 
'G', 'l', 'o', 'b', 'a', 'l',
-       'R', 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'u', 's', '-', 'g', 'o', 
'v', '-', 'w', 'e', 's', 't',
-       '-', '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 
's', '-', 'u', 's', '-', 'g',
-       'o', 'v', '"', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 
'u', 'a', 'l', 'S', 't', 'a',
+       'i', 's', 'o', '-', 'e', 'a', 's', 't', '-', '1', '"', ':', '{', '"', 
'd', 'e', 's', 'c', 'r', 'i',
+       'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'I', 'S', 'O', ' 
', 'E', 'a', 's', 't', '"',
+       '}', ',', '"', 'u', 's', '-', 'i', 's', 'o', '-', 'w', 'e', 's', 't', 
'-', '1', '"', ':', '{', '"',
+       'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 
'U', 'S', ' ', 'I', 'S', 'O',
+       ' ', 'W', 'E', 'S', 'T', '"', '}', '}', '}', ',', '{', '"', 'i', 'd', 
'"', ':', '"', 'a', 'w', 's',
+       '-', 'i', 's', 'o', '-', 'b', '"', ',', '"', 'o', 'u', 't', 'p', 'u', 
't', 's', '"', ':', '{', '"',
+       'd', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 's', 'c', 
'2', 's', '.', 's', 'g', 'o',
+       'v', '.', 'g', 'o', 'v', '"', ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 
'a', 'c', 'k', 'D', 'n', 's',
+       'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'a', 'p', 'i', '.', 'a', 
'w', 's', '.', 's', 'c', 'l',
+       'o', 'u', 'd', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 
'G', 'l', 'o', 'b', 'a', 'l',
+       'R', 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'u', 's', '-', 'i', 's', 
'o', 'b', '-', 'e', 'a', 's',
+       't', '-', '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 'a', 
'w', 's', '-', 'i', 's', 'o',
+       '-', 'b', '"', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 
'u', 'a', 'l', 'S', 't', 'a',
        'c', 'k', '"', ':', 't', 'r', 'u', 'e', ',', '"', 's', 'u', 'p', 'p', 
'o', 'r', 't', 's', 'F', 'I',
        'P', 'S', '"', ':', 't', 'r', 'u', 'e', '}', ',', '"', 'r', 'e', 'g', 
'i', 'o', 'n', 'R', 'e', 'g',
-       'e', 'x', '"', ':', '"', '^', 'u', 's', '\\', '\\', '-', 'g', 'o', 'v', 
'\\', '\\', '-', '\\', '\\', 'w',
-       '+', '\\', '\\', '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', 'r', 
'e', 'g', 'i', 'o', 'n', 's', '"',
-       ':', '{', '"', 'a', 'w', 's', '-', 'u', 's', '-', 'g', 'o', 'v', '-', 
'g', 'l', 'o', 'b', 'a', 'l',
+       'e', 'x', '"', ':', '"', '^', 'u', 's', '\\', '\\', '-', 'i', 's', 'o', 
'b', '\\', '\\', '-', '\\', '\\',
+       'w', '+', '\\', '\\', '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', 
'r', 'e', 'g', 'i', 'o', 'n', 's',
+       '"', ':', '{', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'b', '-', 
'g', 'l', 'o', 'b', 'a', 'l',
        '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 
'n', '"', ':', '"', 'a', 'w',
-       's', '-', 'u', 's', '-', 'g', 'o', 'v', ' ', 'g', 'l', 'o', 'b', 'a', 
'l', ' ', 'r', 'e', 'g', 'i',
-       'o', 'n', '"', '}', ',', '"', 'u', 's', '-', 'g', 'o', 'v', '-', 'e', 
'a', 's', 't', '-', '1', '"',
-       ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 
'"', ':', '"', 'A', 'W', 'S',
-       ' ', 'G', 'o', 'v', 'C', 'l', 'o', 'u', 'd', ' ', '(', 'U', 'S', '-', 
'E', 'a', 's', 't', ')', '"',
-       '}', ',', '"', 'u', 's', '-', 'g', 'o', 'v', '-', 'w', 'e', 's', 't', 
'-', '1', '"', ':', '{', '"',
-       'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 
'A', 'W', 'S', ' ', 'G', 'o',
-       'v', 'C', 'l', 'o', 'u', 'd', ' ', '(', 'U', 'S', '-', 'W', 'e', 's', 
't', ')', '"', '}', '}', '}',
-       ']', ',', '"', 'v', 'e', 'r', 's', 'i', 'o', 'n', '"', ':', '"', '1', 
'.', '1', '"', '}'};
+       's', '-', 'i', 's', 'o', '-', 'b', ' ', 'g', 'l', 'o', 'b', 'a', 'l', ' 
', 'r', 'e', 'g', 'i', 'o',
+       'n', '"', '}', ',', '"', 'u', 's', '-', 'i', 's', 'o', 'b', '-', 'e', 
'a', 's', 't', '-', '1', '"',
+       ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 
'"', ':', '"', 'U', 'S', ' ',
+       'I', 'S', 'O', 'B', ' ', 'E', 'a', 's', 't', ' ', '(', 'O', 'h', 'i', 
'o', ')', '"', '}', ',', '"',
+       'u', 's', '-', 'i', 's', 'o', 'b', '-', 'w', 'e', 's', 't', '-', '1', 
'"', ':', '{', '"', 'd', 'e',
+       's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' 
', 'I', 'S', 'O', 'B', ' ',
+       'W', 'e', 's', 't', '"', '}', '}', '}', ',', '{', '"', 'i', 'd', '"', 
':', '"', 'a', 'w', 's', '-',
+       'i', 's', 'o', '-', 'e', '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', 
's', '"', ':', '{', '"', 'd',
+       'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'c', 'l', 'o', 
'u', 'd', '.', 'a', 'd', 'c',
+       '-', 'e', '.', 'u', 'k', '"', ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 
'a', 'c', 'k', 'D', 'n', 's',
+       'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'a', 'p', 'i', '.', 'c', 
'l', 'o', 'u', 'd', '-', 'a',
+       'w', 's', '.', 'a', 'd', 'c', '-', 'e', '.', 'u', 'k', '"', ',', '"', 
'i', 'm', 'p', 'l', 'i', 'c',
+       'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 'R', 'e', 'g', 'i', 'o', 'n', 
'"', ':', '"', 'e', 'u', '-',
+       'i', 's', 'o', 'e', '-', 'w', 'e', 's', 't', '-', '1', '"', ',', '"', 
'n', 'a', 'm', 'e', '"', ':',
+       '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'e', '"', ',', '"', 's', 
'u', 'p', 'p', 'o', 'r', 't',
+       's', 'D', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', '"', ':', 't', 'r', 
'u', 'e', ',', '"', 's', 'u',
+       'p', 'p', 'o', 'r', 't', 's', 'F', 'I', 'P', 'S', '"', ':', 't', 'r', 
'u', 'e', '}', ',', '"', 'r',
+       'e', 'g', 'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', '"', ':', '"', '^', 
'e', 'u', '\\', '\\', '-', 'i',
+       's', 'o', 'e', '\\', '\\', '-', '\\', '\\', 'w', '+', '\\', '\\', '-', 
'\\', '\\', 'd', '+', '$', '"', ',',
+       '"', 'r', 'e', 'g', 'i', 'o', 'n', 's', '"', ':', '{', '"', 'a', 'w', 
's', '-', 'i', 's', 'o', '-',
+       'e', '-', 'g', 'l', 'o', 'b', 'a', 'l', '"', ':', '{', '"', 'd', 'e', 
's', 'c', 'r', 'i', 'p', 't',
+       'i', 'o', 'n', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 
'e', ' ', 'g', 'l', 'o', 'b',
+       'a', 'l', ' ', 'r', 'e', 'g', 'i', 'o', 'n', '"', '}', ',', '"', 'e', 
'u', '-', 'i', 's', 'o', 'e',
+       '-', 'w', 'e', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 
'c', 'r', 'i', 'p', 't', 'i',
+       'o', 'n', '"', ':', '"', 'E', 'U', ' ', 'I', 'S', 'O', 'E', ' ', 'W', 
'e', 's', 't', '"', '}', '}',
+       '}', ',', '{', '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', '-', 'i', 
's', 'o', '-', 'f', '"', ',',
+       '"', 'o', 'u', 't', 'p', 'u', 't', 's', '"', ':', '{', '"', 'd', 'n', 
's', 'S', 'u', 'f', 'f', 'i',
+       'x', '"', ':', '"', 'c', 's', 'p', '.', 'h', 'c', 'i', '.', 'i', 'c', 
'.', 'g', 'o', 'v', '"', ',',
+       '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', 'S', 
'u', 'f', 'f', 'i', 'x', '"',
+       ':', '"', 'a', 'p', 'i', '.', 'a', 'w', 's', '.', 'h', 'c', 'i', '.', 
'i', 'c', '.', 'g', 'o', 'v',
+       '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', 'l', 'o', 
'b', 'a', 'l', 'R', 'e', 'g',
+       'i', 'o', 'n', '"', ':', '"', 'u', 's', '-', 'i', 's', 'o', 'f', '-', 
's', 'o', 'u', 't', 'h', '-',
+       '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 's', 
'-', 'i', 's', 'o', '-', 'f',
+       '"', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 'u', 'a', 
'l', 'S', 't', 'a', 'c', 'k',
+       '"', ':', 't', 'r', 'u', 'e', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 
't', 's', 'F', 'I', 'P', 'S',
+       '"', ':', 't', 'r', 'u', 'e', '}', ',', '"', 'r', 'e', 'g', 'i', 'o', 
'n', 'R', 'e', 'g', 'e', 'x',
+       '"', ':', '"', '^', 'u', 's', '\\', '\\', '-', 'i', 's', 'o', 'f', 
'\\', '\\', '-', '\\', '\\', 'w', '+',
+       '\\', '\\', '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 
'g', 'i', 'o', 'n', 's', '"', ':',
+       '{', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'f', '-', 'g', 'l', 
'o', 'b', 'a', 'l', '"', ':',
+       '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', 
':', '"', 'a', 'w', 's', '-',
+       'i', 's', 'o', '-', 'f', ' ', 'g', 'l', 'o', 'b', 'a', 'l', ' ', 'r', 
'e', 'g', 'i', 'o', 'n', '"',
+       '}', ',', '"', 'u', 's', '-', 'i', 's', 'o', 'f', '-', 'e', 'a', 's', 
't', '-', '1', '"', ':', '{',
+       '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', 
'"', 'U', 'S', ' ', 'I', 'S',
+       'O', 'F', ' ', 'E', 'A', 'S', 'T', '"', '}', ',', '"', 'u', 's', '-', 
'i', 's', 'o', 'f', '-', 's',
+       'o', 'u', 't', 'h', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 
'r', 'i', 'p', 't', 'i', 'o',
+       'n', '"', ':', '"', 'U', 'S', ' ', 'I', 'S', 'O', 'F', ' ', 'S', 'O', 
'U', 'T', 'H', '"', '}', '}',
+       '}', ',', '{', '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', '-', 'u', 
's', '-', 'g', 'o', 'v', '"',
+       ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', '"', ':', '{', '"', 'd', 
'n', 's', 'S', 'u', 'f', 'f',
+       'i', 'x', '"', ':', '"', 'a', 'm', 'a', 'z', 'o', 'n', 'a', 'w', 's', 
'.', 'c', 'o', 'm', '"', ',',
+       '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', 'S', 
'u', 'f', 'f', 'i', 'x', '"',
+       ':', '"', 'a', 'p', 'i', '.', 'a', 'w', 's', '"', ',', '"', 'i', 'm', 
'p', 'l', 'i', 'c', 'i', 't',
+       'G', 'l', 'o', 'b', 'a', 'l', 'R', 'e', 'g', 'i', 'o', 'n', '"', ':', 
'"', 'u', 's', '-', 'g', 'o',
+       'v', '-', 'w', 'e', 's', 't', '-', '1', '"', ',', '"', 'n', 'a', 'm', 
'e', '"', ':', '"', 'a', 'w',
+       's', '-', 'u', 's', '-', 'g', 'o', 'v', '"', ',', '"', 's', 'u', 'p', 
'p', 'o', 'r', 't', 's', 'D',
+       'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', '"', ':', 't', 'r', 'u', 'e', 
',', '"', 's', 'u', 'p', 'p',
+       'o', 'r', 't', 's', 'F', 'I', 'P', 'S', '"', ':', 't', 'r', 'u', 'e', 
'}', ',', '"', 'r', 'e', 'g',
+       'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', '"', ':', '"', '^', 'u', 's', 
'\\', '\\', '-', 'g', 'o', 'v',
+       '\\', '\\', '-', '\\', '\\', 'w', '+', '\\', '\\', '-', '\\', '\\', 
'd', '+', '$', '"', ',', '"', 'r', 'e',
+       'g', 'i', 'o', 'n', 's', '"', ':', '{', '"', 'a', 'w', 's', '-', 'u', 
's', '-', 'g', 'o', 'v', '-',
+       'g', 'l', 'o', 'b', 'a', 'l', '"', ':', '{', '"', 'd', 'e', 's', 'c', 
'r', 'i', 'p', 't', 'i', 'o',
+       'n', '"', ':', '"', 'a', 'w', 's', '-', 'u', 's', '-', 'g', 'o', 'v', ' 
', 'g', 'l', 'o', 'b', 'a',
+       'l', ' ', 'r', 'e', 'g', 'i', 'o', 'n', '"', '}', ',', '"', 'u', 's', 
'-', 'g', 'o', 'v', '-', 'e',
+       'a', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 
'i', 'p', 't', 'i', 'o', 'n',
+       '"', ':', '"', 'A', 'W', 'S', ' ', 'G', 'o', 'v', 'C', 'l', 'o', 'u', 
'd', ' ', '(', 'U', 'S', '-',
+       'E', 'a', 's', 't', ')', '"', '}', ',', '"', 'u', 's', '-', 'g', 'o', 
'v', '-', 'w', 'e', 's', 't',
+       '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 
'i', 'o', 'n', '"', ':', '"',
+       'A', 'W', 'S', ' ', 'G', 'o', 'v', 'C', 'l', 'o', 'u', 'd', ' ', '(', 
'U', 'S', '-', 'W', 'e', 's',
+       't', ')', '"', '}', '}', '}', ']', ',', '"', 'v', 'e', 'r', 's', 'i', 
'o', 'n', '"', ':', '"', '1',
+       '.', '1', '"', '}'};
 
 const struct aws_byte_cursor aws_s3_endpoint_resolver_partitions = {
-       .len = 4878,
+       .len = 4904,
        .ptr = (uint8_t *) s_generated_array
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-s3-0.11.5/source/s3_meta_request.c 
new/aws-c-s3-0.12.0/source/s3_meta_request.c
--- old/aws-c-s3-0.11.5/source/s3_meta_request.c        2026-01-13 
22:39:24.000000000 +0100
+++ new/aws-c-s3-0.12.0/source/s3_meta_request.c        2026-03-23 
18:14:51.000000000 +0100
@@ -1425,8 +1425,17 @@
                     }
                     if (request->part_range_end != object_range_end) {
                         /* In the case where the object size is less than the 
range requested. It must be return the
-                         * last part to the end of the object. */
-                        if (object_size != object_range_end + 1 || 
request->part_range_end < object_range_end) {
+                         * last part to the end of the object.
+                         * Note: that when get with part 1 is used we dont 
know how big the buffer will be. We
+                         * optimistically allocate part sized buffer, and see 
if its enough. If its over, the req will
+                         * get canceled. So in that case skip validation on 
expected size.
+                         */
+                        bool is_unknown_len_part_req =
+                            request->request_type == 
AWS_S3_REQUEST_TYPE_GET_OBJECT &&
+                            request->request_tag == 
AWS_S3_AUTO_RANGE_GET_REQUEST_TYPE_GET_OBJECT_WITH_PART_NUMBER_1;
+
+                        if (!is_unknown_len_part_req &&
+                            (object_size != object_range_end + 1 || 
request->part_range_end < object_range_end)) {
                             /* Something went wrong if it's matching. Log the 
error. */
                             AWS_LOGF_ERROR(
                                 AWS_LS_S3_META_REQUEST,
@@ -1536,7 +1545,7 @@
 
     if (request->send_data.response_body.capacity == 0) {
         /* Make sure that request is get, since puts can also have ticket 
allocated, which is used for request body. */
-        if (request->request_type == AWS_S3_REQUEST_TYPE_GET_OBJECT && 
request->ticket != NULL) {
+        if (successful_response && request->request_type == 
AWS_S3_REQUEST_TYPE_GET_OBJECT && request->ticket != NULL) {
             request->send_data.response_body = 
aws_s3_buffer_ticket_claim(request->ticket);
         } else {
             size_t buffer_size = s_dynamic_body_initial_buf_size;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-s3-0.11.5/source/s3_request.c 
new/aws-c-s3-0.12.0/source/s3_request.c
--- old/aws-c-s3-0.11.5/source/s3_request.c     2026-01-13 22:39:24.000000000 
+0100
+++ new/aws-c-s3-0.12.0/source/s3_request.c     2026-03-23 18:14:51.000000000 
+0100
@@ -55,6 +55,14 @@
     return request;
 }
 
+uint64_t aws_s3_request_get_payload_size(struct aws_s3_request *request) {
+    uint64_t result = 0;
+    if (aws_sub_u64_checked(request->part_range_end, 
request->part_range_start, &result) != AWS_OP_SUCCESS) {
+        return 0;
+    }
+    return result + 1;
+}
+
 static void s_populate_metrics_from_message(struct aws_s3_request *request, 
struct aws_http_message *message) {
     struct aws_byte_cursor out_path;
     AWS_ZERO_STRUCT(out_path);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-s3-0.11.5/tests/CMakeLists.txt 
new/aws-c-s3-0.12.0/tests/CMakeLists.txt
--- old/aws-c-s3-0.11.5/tests/CMakeLists.txt    2026-01-13 22:39:24.000000000 
+0100
+++ new/aws-c-s3-0.12.0/tests/CMakeLists.txt    2026-03-23 18:14:51.000000000 
+0100
@@ -447,6 +447,7 @@
 add_test_case(test_s3_buffer_pool_special_size_with_limits)
 add_test_case(test_s3_buffer_pool_special_size_mixed)
 add_test_case(test_s3_buffer_pool_special_size_trim)
+add_test_case(test_s3_buffer_pool_reserve_tiny_chunks)
 
 add_net_test_case(client_update_upload_part_timeout)
 add_net_test_case(client_meta_request_override_part_size)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/aws-c-s3-0.11.5/tests/fuzz/fuzz_buffer_pool_special_size.c 
new/aws-c-s3-0.12.0/tests/fuzz/fuzz_buffer_pool_special_size.c
--- old/aws-c-s3-0.11.5/tests/fuzz/fuzz_buffer_pool_special_size.c      
2026-01-13 22:39:24.000000000 +0100
+++ new/aws-c-s3-0.12.0/tests/fuzz/fuzz_buffer_pool_special_size.c      
2026-03-23 18:14:51.000000000 +0100
@@ -179,17 +179,14 @@
         } else if (size_type == 1) {
             /* Primary storage allocation (below primary_cutoff) */
             reservation_size = 1024 + (size_value % (primary_cutoff - 1024));
-            is_primary = true;
         } else {
             /* Secondary storage allocation (above primary_cutoff, below 
smallest special size) */
             size_t secondary_range = special_sizes[0] - primary_cutoff - 1;
             if (secondary_range > 0) {
                 reservation_size = primary_cutoff + 1 + (size_value % 
secondary_range);
-                is_secondary = true;
             } else {
                 /* Not enough space for secondary, use primary instead */
                 reservation_size = 1024 + (size_value % (primary_cutoff - 
1024));
-                is_primary = true;
             }
         }
 
@@ -227,6 +224,25 @@
         int error = aws_future_s3_buffer_ticket_get_error(future);
         AWS_FATAL_ASSERT(error == AWS_OP_SUCCESS);
 
+        /* Acquire the ticket */
+        struct aws_s3_buffer_ticket *ticket = 
aws_future_s3_buffer_ticket_get_result_by_move(future);
+        AWS_FATAL_ASSERT(ticket != NULL);
+
+        enum aws_s3_default_buffer_pool_reserved_from reserved_from =
+            aws_s3_default_buffer_pool_get_ticket_reserved_from(ticket->impl);
+
+        if (reserved_from == AWS_S3_BUFFER_POOL_RESERVED_FROM_SPECIAL) {
+            AWS_FATAL_ASSERT(is_special); /* we know in advance all special 
blocks that must be reserved.*/
+            is_special = true;
+        } else if (reserved_from == AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY) {
+            is_primary = true; /* for primary and secondary there is a lot 
more rules so rely on pool for where its
+                                  allocated from*/
+        } else if (reserved_from == 
AWS_S3_BUFFER_POOL_RESERVED_FROM_SECONDARY) {
+            is_secondary = true;
+        } else {
+            AWS_FATAL_ASSERT(false);
+        }
+
         /* Update expected reserved based on type we determined earlier 
(including accidental special size check) */
         if (is_special) {
             expected_special_reserved += reservation_size;
@@ -248,10 +264,6 @@
             AWS_FATAL_ASSERT(after_reserve_stats.secondary_reserved == 
expected_secondary_reserved);
         }
 
-        /* Acquire the ticket */
-        struct aws_s3_buffer_ticket *ticket = 
aws_future_s3_buffer_ticket_get_result_by_move(future);
-        AWS_FATAL_ASSERT(ticket != NULL);
-
         /* Claim the buffer to verify it works */
         struct aws_byte_buf buf = aws_s3_buffer_ticket_claim(ticket);
         AWS_FATAL_ASSERT(buf.buffer != NULL);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/aws-c-s3-0.11.5/tests/s3_default_buffer_pool_tests.c 
new/aws-c-s3-0.12.0/tests/s3_default_buffer_pool_tests.c
--- old/aws-c-s3-0.11.5/tests/s3_default_buffer_pool_tests.c    2026-01-13 
22:39:24.000000000 +0100
+++ new/aws-c-s3-0.12.0/tests/s3_default_buffer_pool_tests.c    2026-03-23 
18:14:51.000000000 +0100
@@ -139,6 +139,7 @@
 
     struct aws_future_s3_buffer_ticket *future2 = 
aws_s3_default_buffer_pool_reserve(
         buffer_pool, (struct aws_s3_buffer_pool_reserve_meta){.size = 
MB_TO_BYTES(32)});
+
     ASSERT_NOT_NULL(future2);
     ASSERT_TRUE(aws_future_s3_buffer_ticket_is_done(future2));
     ASSERT_INT_EQUALS(aws_future_s3_buffer_ticket_get_error(future2), 
AWS_OP_SUCCESS);
@@ -147,6 +148,9 @@
     struct aws_byte_buf buf2 = aws_s3_buffer_ticket_claim(ticket2);
     ASSERT_NOT_NULL(buf2.buffer);
 
+    struct aws_s3_default_buffer_pool_usage_stats stats = 
aws_s3_default_buffer_pool_get_usage(buffer_pool);
+    ASSERT_UINT_EQUALS(0, stats.primary_allocated);
+
     for (size_t i = 0; i < 6; ++i) {
         aws_s3_buffer_ticket_release(tickets[i]);
         aws_future_s3_buffer_ticket_release(ticket_futures[i]);
@@ -234,11 +238,15 @@
     struct aws_s3_buffer_ticket *tickets[112];
     struct aws_future_s3_buffer_ticket *ticket_futures[112];
     for (size_t i = 0; i < 112; ++i) {
+        AWS_LOGF_DEBUG(0, "reserving buffer %zu", i + 1);
         ticket_futures[i] = aws_s3_default_buffer_pool_reserve(
             buffer_pool, (struct aws_s3_buffer_pool_reserve_meta){.size = 
MB_TO_BYTES(8)});
         ASSERT_TRUE(aws_future_s3_buffer_ticket_is_done(ticket_futures[i]));
         
ASSERT_INT_EQUALS(aws_future_s3_buffer_ticket_get_error(ticket_futures[i]), 
AWS_OP_SUCCESS);
         tickets[i] = 
aws_future_s3_buffer_ticket_get_result_by_move(ticket_futures[i]);
+        ASSERT_INT_EQUALS(
+            
aws_s3_default_buffer_pool_get_ticket_reserved_from(tickets[i]->impl),
+            AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY);
         struct aws_byte_buf buf = aws_s3_buffer_ticket_claim(tickets[i]);
         ASSERT_NOT_NULL(buf.buffer);
     }
@@ -258,6 +266,9 @@
     }
 
     ASSERT_NOT_NULL(state.ticket);
+    ASSERT_INT_EQUALS(
+        
aws_s3_default_buffer_pool_get_ticket_reserved_from(state.ticket->impl),
+        AWS_S3_BUFFER_POOL_RESERVED_FROM_PRIMARY);
 
     aws_s3_buffer_ticket_release(state.ticket);
     aws_future_s3_buffer_ticket_release(over_future);
@@ -635,3 +646,36 @@
 AWS_TEST_CASE(
     test_s3_buffer_pool_forced_buffer_wont_stop_reservations,
     s_test_s3_buffer_pool_forced_buffer_wont_stop_reservations)
+
+/* Test small requests reserve expected amount of mem without rounding up to 
part size. */
+static int s_test_s3_buffer_pool_reserve_tiny_chunks(struct aws_allocator 
*allocator, void *ctx) {
+    (void)ctx;
+    const size_t chunk_size = MB_TO_BYTES(8);
+    const size_t small_size = KB_TO_BYTES(128);
+    const size_t mem_limit = GB_TO_BYTES(1);
+    struct aws_s3_buffer_pool *buffer_pool = aws_s3_default_buffer_pool_new(
+        allocator, (struct aws_s3_buffer_pool_config){.part_size = chunk_size, 
.memory_limit = mem_limit});
+
+    struct aws_s3_buffer_ticket *ticket = NULL;
+    struct aws_future_s3_buffer_ticket *future =
+        aws_s3_default_buffer_pool_reserve(buffer_pool, (struct 
aws_s3_buffer_pool_reserve_meta){.size = small_size});
+    ASSERT_TRUE(aws_future_s3_buffer_ticket_is_done(future));
+    ASSERT_INT_EQUALS(aws_future_s3_buffer_ticket_get_error(future), 
AWS_OP_SUCCESS);
+    ticket = aws_future_s3_buffer_ticket_get_result_by_move(future);
+    struct aws_byte_buf buf = aws_s3_buffer_ticket_claim(ticket);
+    ASSERT_UINT_EQUALS(small_size, buf.capacity);
+
+    struct aws_s3_default_buffer_pool_usage_stats stats = 
aws_s3_default_buffer_pool_get_usage(buffer_pool);
+    ASSERT_INT_EQUALS(small_size, stats.secondary_used);
+
+    aws_s3_buffer_ticket_release(ticket);
+    aws_future_s3_buffer_ticket_release(future);
+
+    stats = aws_s3_default_buffer_pool_get_usage(buffer_pool);
+    ASSERT_INT_EQUALS(0, stats.secondary_used);
+
+    /* Cleanup */
+    aws_s3_default_buffer_pool_destroy(buffer_pool);
+    return 0;
+}
+AWS_TEST_CASE(test_s3_buffer_pool_reserve_tiny_chunks, 
s_test_s3_buffer_pool_reserve_tiny_chunks)

Reply via email to