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]