This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git


The following commit(s) were added to refs/heads/main by this push:
     new 8654067b0 PROTON-2950: Make pn_buffer_t use more resilient to 
allocation failure
8654067b0 is described below

commit 8654067b0b742a173632d4d51c17fcd87f737e88
Author: Andrew Stitcher <[email protected]>
AuthorDate: Thu Jul 16 15:32:22 2026 -0400

    PROTON-2950: Make pn_buffer_t use more resilient to allocation failure
    
    * Also use a more efficient scheme for doubling buffer size
---
 c/src/core/buffer.c    | 28 +++++++++++++++-------------
 c/src/core/engine.c    |  3 ++-
 c/src/core/transport.c |  3 ++-
 c/src/core/util.h      | 11 +++++++++++
 4 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/c/src/core/buffer.c b/c/src/core/buffer.c
index dc3a753d6..dbc7a451f 100644
--- a/c/src/core/buffer.c
+++ b/c/src/core/buffer.c
@@ -115,25 +115,27 @@ static size_t pni_buffer_tail_space(pn_buffer_t *buf)
 
 int pn_buffer_ensure(pn_buffer_t *buf, size_t size)
 {
+  if (pn_buffer_available(buf) >= size) return 0;
+
   size_t old_capacity = buf->capacity;
   size_t old_head = pni_buffer_head(buf);
   bool wrapped = pni_buffer_wrapped(buf);
 
-  while (pn_buffer_available(buf) < size) {
-    buf->capacity = 2*(buf->capacity ? buf->capacity : 16);
-  }
+  uint32_t needed = (uint32_t)(buf->size + size);
+  if (needed < 32) needed = 32;
+  uint32_t new_capacity = pni_round_up_pow2(needed);
 
-  if (buf->capacity != old_capacity) {
-    char* new_bytes = (char *) pni_mem_subreallocate(PN_CLASSCLASS(pn_buffer), 
buf, buf->bytes, buf->capacity);
-    if (new_bytes) {
-      buf->bytes = new_bytes;
+  char* new_bytes = (char *) pni_mem_subreallocate(PN_CLASSCLASS(pn_buffer), 
buf, buf->bytes, new_capacity);
+  if (!new_bytes) {
+    return PN_OUT_OF_MEMORY;
+  }
+  buf->bytes = new_bytes;
+  buf->capacity = new_capacity;
 
-      if (wrapped) {
-          size_t n = old_capacity - old_head;
-          memmove(buf->bytes + buf->capacity - n, buf->bytes + old_head, n);
-          buf->start = buf->capacity - n;
-      }
-    }
+  if (wrapped) {
+    size_t n = old_capacity - old_head;
+    memmove(buf->bytes + buf->capacity - n, buf->bytes + old_head, n);
+    buf->start = buf->capacity - n;
   }
 
   return 0;
diff --git a/c/src/core/engine.c b/c/src/core/engine.c
index f5eafbad1..577499210 100644
--- a/c/src/core/engine.c
+++ b/c/src/core/engine.c
@@ -2329,7 +2329,8 @@ ssize_t pn_link_send(pn_link_t *sender, const char 
*bytes, size_t n)
   pn_delivery_t *current = pn_link_current(sender);
   if (!current) return PN_EOS;
   if (!bytes || !n) return 0;
-  pn_buffer_append(current->bytes, bytes, n);
+  int err = pn_buffer_append(current->bytes, bytes, n);
+  if (err) return err;
   sender->session->outgoing_bytes += n;
   pni_add_tpwork(current);
   return n;
diff --git a/c/src/core/transport.c b/c/src/core/transport.c
index e074c6682..ff7250ee1 100644
--- a/c/src/core/transport.c
+++ b/c/src/core/transport.c
@@ -1424,7 +1424,8 @@ int pn_do_transfer(pn_transport_t *transport, uint8_t 
frame_type, uint16_t chann
   }
 
   if (delivery) {
-    pn_buffer_append(delivery->bytes, payload.start, payload.size);
+    int err = pn_buffer_append(delivery->bytes, payload.start, payload.size);
+    if (err) return pn_do_error(transport, "amqp:resource-limit-exceeded", 
"out of memory buffering incoming delivery");
     if (more) {
       if (!link->more_pending) {
         if (!id_present) {
diff --git a/c/src/core/util.h b/c/src/core/util.h
index 7d7ac55a6..df4f67964 100644
--- a/c/src/core/util.h
+++ b/c/src/core/util.h
@@ -154,6 +154,17 @@ static inline void pni_switch_to_raw_multiple(pn_rwbytes_t 
*scratch, pn_data_t *
   }
 }
 
+/* Round up to the nearest power of two >= n. If n > 0x80000000 the result 
wraps to 0. */
+static inline uint32_t pni_round_up_pow2(uint32_t n) {
+  n--;
+  n |= n >> 1;
+  n |= n >> 2;
+  n |= n >> 4;
+  n |= n >> 8;
+  n |= n >> 16;
+  return n + 1;
+}
+
 static inline void pni_write16(char *bytes, uint16_t value)
 {
   bytes[0] = 0xFF & (value >> 8);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to