diff -Nru librabbitmq-0.15.0/debian/changelog librabbitmq-0.15.0/debian/changelog --- librabbitmq-0.15.0/debian/changelog 2026-06-10 16:29:23.000000000 +0200 +++ librabbitmq-0.15.0/debian/changelog 2026-08-15 12:27:08.000000000 +0200 @@ -1,3 +1,14 @@ +librabbitmq (0.15.0-1+deb13u2) trixie-security; urgency=medium + + * [9bc0956] d/patches/CVE-2026-59986.patch: added from upstream. + Fix amqp_decode_bytes size_t integer overflow bypasses bounds check on + 32-bit (OOB read) (GHSA-jgjf-7fwf-f3c7, CVE-2026-59986) + * [58e0219] d/patches/CVE-2026-61547.patch: added from upstream. + Fix Heap Buffer Overflow in amqp_send_frame() When Serializing Oversized + AMQP_FRAME_BODY (GHSA-hfjv-vcp3-39wh, CVE-2026-61547) + + -- Florian Ernst Sat, 15 Aug 2026 12:27:08 +0200 + librabbitmq (0.15.0-1+deb13u1) trixie-security; urgency=medium * [b57bf8d] d/patches/CVE-2026-44235.patch: added from upstream. diff -Nru librabbitmq-0.15.0/debian/patches/CVE-2026-59986.patch librabbitmq-0.15.0/debian/patches/CVE-2026-59986.patch --- librabbitmq-0.15.0/debian/patches/CVE-2026-59986.patch 1970-01-01 01:00:00.000000000 +0100 +++ librabbitmq-0.15.0/debian/patches/CVE-2026-59986.patch 2026-08-15 12:24:04.000000000 +0200 @@ -0,0 +1,165 @@ +From 1bb1b9b1b7bc69eede6295e95fa9527c731f0798 Mon Sep 17 00:00:00 2001 +From: Claude +Date: Sun, 21 Jun 2026 23:12:38 +0000 +Subject: [PATCH] Fix size_t overflow in amqp_decode_bytes bounds check + (GHSA-jgjf-7fwf-f3c7) +Origin: upstream, https://github.com/alanxz/rabbitmq-c/commit/1bb1b9b1b7bc69eede6295e95fa9527c731f0798 +Applied-Upstream: v0.17.0, https://github.com/alanxz/rabbitmq-c/releases/tag/v0.17.0 + +The bounds check in amqp_decode_bytes computed (offset + len) and compared +it against the buffer length. When offset + len exceeds SIZE_MAX the addition +wraps around, which an attacker can trigger on 32-bit platforms by supplying a +large BYTES/UTF8 wire length (len is read from the AMQP frame as a uint32_t). +The wrap made the check pass and produced an amqp_bytes_t with a multi-gigabyte +length pointing into a small frame buffer, leading to an out-of-bounds read +(information disclosure or crash) when the value was later processed. + +Rewrite the check to compare len against the remaining space +(len <= encoded.len - offset) which cannot overflow because offset is always +<= encoded.len. Apply the same hardening to amqp_encode_bytes for consistency. + +Add tests/test_decode_bytes.c covering normal decodes, plain out-of-bounds +lengths, and the overflow/wraparound cases from the advisory. + +Reported by TristanInSec. + +Co-Authored-By: Claude Opus 4.8 +Claude-Session: https://claude.ai/code/session_01DDZRguQKhqDoqP5NFfDmFs +--- + librabbitmq/amqp_private.h | 12 +++++- + tests/CMakeLists.txt | 4 ++ + tests/test_decode_bytes.c | 84 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 98 insertions(+), 2 deletions(-) + create mode 100644 tests/test_decode_bytes.c + +Index: git/librabbitmq/amqp_private.h +=================================================================== +--- git.orig/librabbitmq/amqp_private.h ++++ git/librabbitmq/amqp_private.h +@@ -299,7 +299,10 @@ static inline int amqp_encode_bytes(amqp + if (input.len == 0) { + return 1; + } +- if ((*offset = o + input.len) <= encoded.len) { ++ *offset = o + input.len; ++ /* Compare against remaining space rather than o + input.len to avoid size_t ++ * overflow; o <= encoded.len, so encoded.len - o cannot underflow. */ ++ if (o <= encoded.len && input.len <= encoded.len - o) { + memcpy(amqp_offset(encoded.bytes, o), input.bytes, input.len); + return 1; + } else { +@@ -310,7 +313,12 @@ static inline int amqp_encode_bytes(amqp + static inline int amqp_decode_bytes(amqp_bytes_t encoded, size_t *offset, + amqp_bytes_t *output, size_t len) { + size_t o = *offset; +- if ((*offset = o + len) <= encoded.len) { ++ *offset = o + len; ++ /* Compare against remaining space rather than o + len: with len read from the ++ * wire (uint32_t), o + len can overflow size_t on 32-bit platforms and wrap ++ * past the check, yielding an out-of-bounds amqp_bytes_t. o <= encoded.len, ++ * so encoded.len - o cannot underflow. */ ++ if (o <= encoded.len && len <= encoded.len - o) { + output->bytes = amqp_offset(encoded.bytes, o); + output->len = len; + return 1; +Index: git/tests/CMakeLists.txt +=================================================================== +--- git.orig/tests/CMakeLists.txt ++++ git/tests/CMakeLists.txt +@@ -41,3 +41,7 @@ add_executable(test_merge_capabilities t + target_link_libraries(test_merge_capabilities rabbitmq-static) + add_test(merge_capabilities test_merge_capabilities) + ++add_executable(test_decode_bytes test_decode_bytes.c) ++target_link_libraries(test_decode_bytes rabbitmq-static) ++add_test(decode_bytes test_decode_bytes) ++ +Index: git/tests/test_decode_bytes.c +=================================================================== +--- /dev/null ++++ git/tests/test_decode_bytes.c +@@ -0,0 +1,84 @@ ++// Copyright 2007 - 2021, Alan Antonuk and the rabbitmq-c contributors. ++// SPDX-License-Identifier: mit ++ ++#include ++#include ++#include ++ ++#include "amqp_private.h" ++ ++/* Regression test for GHSA-jgjf-7fwf-f3c7: a size_t integer overflow in ++ * amqp_decode_bytes bypassed the bounds check on 32-bit systems, producing an ++ * out-of-bounds amqp_bytes_t (information disclosure / crash). The check must ++ * reject any (offset, len) pair that would read past the end of the buffer, ++ * including ones where offset + len wraps around SIZE_MAX. */ ++ ++static int failures = 0; ++ ++static void expect_reject(const char *name, amqp_bytes_t encoded, size_t offset, ++ size_t len) { ++ amqp_bytes_t output; ++ size_t off = offset; ++ output.bytes = NULL; ++ output.len = 0; ++ if (amqp_decode_bytes(encoded, &off, &output, len)) { ++ fprintf(stderr, ++ "FAIL %s: amqp_decode_bytes accepted an out-of-bounds length " ++ "(offset=%zu len=%zu buffer=%zu) -> output.len=%zu\n", ++ name, offset, len, encoded.len, output.len); ++ failures++; ++ } ++} ++ ++static void expect_accept(const char *name, amqp_bytes_t encoded, size_t offset, ++ size_t len) { ++ amqp_bytes_t output; ++ size_t off = offset; ++ output.bytes = NULL; ++ output.len = 0; ++ if (!amqp_decode_bytes(encoded, &off, &output, len)) { ++ fprintf(stderr, ++ "FAIL %s: amqp_decode_bytes rejected a valid length " ++ "(offset=%zu len=%zu buffer=%zu)\n", ++ name, offset, len, encoded.len); ++ failures++; ++ return; ++ } ++ if (output.len != len || output.bytes != amqp_offset(encoded.bytes, offset)) { ++ fprintf(stderr, "FAIL %s: amqp_decode_bytes produced wrong output\n", name); ++ failures++; ++ } ++} ++ ++int main(void) { ++ char buffer[16]; ++ amqp_bytes_t encoded; ++ encoded.bytes = buffer; ++ encoded.len = sizeof(buffer); ++ ++ /* Normal, in-bounds decodes still work. */ ++ expect_accept("full buffer", encoded, 0, sizeof(buffer)); ++ expect_accept("partial at offset", encoded, 4, 8); ++ expect_accept("zero length", encoded, 8, 0); ++ ++ /* Plain out-of-bounds (no overflow) is rejected. */ ++ expect_reject("len past end", encoded, 0, sizeof(buffer) + 1); ++ expect_reject("offset past end", encoded, sizeof(buffer) + 1, 0); ++ ++ /* The core of the advisory: a wire length large enough that offset + len ++ * wraps around SIZE_MAX. On 32-bit platforms a uint32_t length of ++ * 0xFFFFFFF5 with a small offset wraps to a tiny value; on any platform we ++ * can force the wrap with a len near SIZE_MAX. Both must be rejected rather ++ * than producing a multi-gigabyte amqp_bytes_t into a small buffer. */ ++ expect_reject("overflow to zero", encoded, 11, (size_t)0 - 11); ++ expect_reject("overflow wraps small", encoded, 16, (size_t)0 - 8); ++ expect_reject("max len", encoded, 1, (size_t)-1); ++ expect_reject("32-bit style len", encoded, 11, (size_t)0xFFFFFFF5u); ++ ++ if (failures) { ++ fprintf(stderr, "%d test(s) failed\n", failures); ++ return 1; ++ } ++ printf("all amqp_decode_bytes bounds tests passed\n"); ++ return 0; ++} diff -Nru librabbitmq-0.15.0/debian/patches/CVE-2026-61547.patch librabbitmq-0.15.0/debian/patches/CVE-2026-61547.patch --- librabbitmq-0.15.0/debian/patches/CVE-2026-61547.patch 1970-01-01 01:00:00.000000000 +0100 +++ librabbitmq-0.15.0/debian/patches/CVE-2026-61547.patch 2026-08-15 12:24:04.000000000 +0200 @@ -0,0 +1,121 @@ +From 02d278663f3a93db9fe4fb4e7e34dc96b83c107b Mon Sep 17 00:00:00 2001 +From: Claude +Date: Mon, 22 Jun 2026 11:38:11 +0000 +Subject: [PATCH] Fix heap buffer overflow in amqp_frame_to_bytes for oversized + body frames +Origin: upstream, https://github.com/alanxz/rabbitmq-c/commit/02d278663f3a93db9fe4fb4e7e34dc96b83c107b +Applied-Upstream: v0.17.0, https://github.com/alanxz/rabbitmq-c/releases/tag/v0.17.0 + +amqp_send_frame() -> amqp_frame_to_bytes() copied +frame.payload.body_fragment.len bytes into the outbound buffer without +validating that the body fragment fit within the allocated frame buffer. +An application passing an oversized AMQP_FRAME_BODY to the public +amqp_send_frame() API could trigger a heap out-of-bounds write. + +Bound the body fragment to the usable payload size +(buffer.len - HEADER_SIZE - FOOTER_SIZE), returning +AMQP_STATUS_BAD_AMQP_DATA when it does not fit. Add a regression test. + +Fixes GHSA-hfjv-vcp3-39wh + +Co-Authored-By: Claude Opus 4.8 +Claude-Session: https://claude.ai/code/session_01LSk2fbTxxZS9STJX6Y9Uge +--- + librabbitmq/amqp_connection.c | 8 +++++ + tests/CMakeLists.txt | 4 +++ + tests/test_send_frame.c | 57 +++++++++++++++++++++++++++++++++++ + 3 files changed, 69 insertions(+) + create mode 100644 tests/test_send_frame.c + +Index: git/librabbitmq/amqp_connection.c +=================================================================== +--- git.orig/librabbitmq/amqp_connection.c ++++ git/librabbitmq/amqp_connection.c +@@ -464,6 +464,14 @@ static int amqp_frame_to_bytes(const amq + case AMQP_FRAME_BODY: { + const amqp_bytes_t *body = &frame->payload.body_fragment; + ++ /* Ensure the body fragment fits within the outbound buffer, leaving ++ * room for the frame header and footer. Without this check an ++ * oversized body fragment would overflow the heap-allocated buffer. */ ++ if (buffer.len < HEADER_SIZE + FOOTER_SIZE || ++ body->len > buffer.len - (HEADER_SIZE + FOOTER_SIZE)) { ++ return AMQP_STATUS_BAD_AMQP_DATA; ++ } ++ + memcpy(amqp_offset(out_frame, HEADER_SIZE), body->bytes, body->len); + + out_frame_len = body->len; +Index: git/tests/CMakeLists.txt +=================================================================== +--- git.orig/tests/CMakeLists.txt ++++ git/tests/CMakeLists.txt +@@ -45,3 +45,6 @@ add_executable(test_decode_bytes test_de + target_link_libraries(test_decode_bytes rabbitmq-static) + add_test(decode_bytes test_decode_bytes) + ++add_executable(test_send_frame test_send_frame.c) ++target_link_libraries(test_send_frame rabbitmq-static) ++add_test(send_frame test_send_frame) +Index: git/tests/test_send_frame.c +=================================================================== +--- /dev/null ++++ git/tests/test_send_frame.c +@@ -0,0 +1,57 @@ ++// Copyright 2007 - 2021, Alan Antonuk and the rabbitmq-c contributors. ++// SPDX-License-Identifier: mit ++ ++#include "amqp_private.h" ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* Regression test for GHSA-hfjv-vcp3-39wh: passing an oversized ++ * AMQP_FRAME_BODY to amqp_send_frame() must not overflow the outbound ++ * buffer. It should be rejected with AMQP_STATUS_BAD_AMQP_DATA. */ ++static void test_oversized_body_frame_rejected(void) { ++ amqp_connection_state_t state = amqp_new_connection(); ++ amqp_frame_t frame; ++ size_t body_len; ++ char *body; ++ int res; ++ ++ if (state == NULL) { ++ fprintf(stderr, "amqp_new_connection failed\n"); ++ abort(); ++ } ++ ++ /* The default outbound buffer is AMQP_DEFAULT_FRAME_SIZE bytes; use a ++ * body fragment that is larger than that buffer can hold. */ ++ body_len = state->outbound_buffer.len + 1024; ++ body = malloc(body_len); ++ if (body == NULL) { ++ fprintf(stderr, "malloc failed\n"); ++ abort(); ++ } ++ memset(body, 'A', body_len); ++ ++ memset(&frame, 0, sizeof(frame)); ++ frame.frame_type = AMQP_FRAME_BODY; ++ frame.channel = 1; ++ frame.payload.body_fragment.bytes = body; ++ frame.payload.body_fragment.len = body_len; ++ ++ res = amqp_send_frame(state, &frame); ++ if (res != AMQP_STATUS_BAD_AMQP_DATA) { ++ fprintf(stderr, "expected AMQP_STATUS_BAD_AMQP_DATA (%d), got %d\n", ++ AMQP_STATUS_BAD_AMQP_DATA, res); ++ abort(); ++ } ++ ++ free(body); ++ amqp_destroy_connection(state); ++} ++ ++int main(void) { ++ test_oversized_body_frame_rejected(); ++ return 0; ++} diff -Nru librabbitmq-0.15.0/debian/patches/series librabbitmq-0.15.0/debian/patches/series --- librabbitmq-0.15.0/debian/patches/series 2026-06-10 16:29:23.000000000 +0200 +++ librabbitmq-0.15.0/debian/patches/series 2026-08-15 12:24:04.000000000 +0200 @@ -1,2 +1,4 @@ CVE-2026-44235.patch CVE-2026-44236.patch +CVE-2026-59986.patch +CVE-2026-61547.patch