release: reliable 1.4.5 - #67
Merged
Merged
Conversation
Bump the two version sites for the 1.4.5 release: project(reliable VERSION) in CMakeLists.txt and RELIABLE_VERSION_FULL / RELIABLE_VERSION_PATCH in reliable.h. The release carries security#26-2 (the fragment reassembly buffer is zeroed after allocation) and security#26-3 (endpoint->config.name is terminated at create and the create-time logs print the caller's name bounded), merged in #66. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cuts 1.4.5 off
mainat 1ea7f61, which merged #66: security#26-2 (the fragment reassembly buffer is zeroed after allocation) and security#26-3 (endpoint->config.nameis NUL terminated at create, and the twelve create-time rejection logs plus the allocation-failure log print the name bounded). This PR is the version bump and the draft notes only — no code changes. Do not tag or publish the release from here.Version sites
Both sites
#64touched for 1.4.4, and no others:grep -rn '1\.4\.4\|RELIABLE_VERSION' --include='*.h' --include='*.c' --include='*.txt' --include='*.md' --include='*.json' .finds only these two version literals (theCLAUDE.mdhit is prose about when the defines were added, at 1.3.0, andreliable.pc.intakes@PROJECT_VERSION@from CMake, so both follow without editing).CMakeLists.txtproject(reliable VERSION 1.4.4 LANGUAGES C)→1.4.5reliable.h#define RELIABLE_VERSION_FULL "1.4.4"→"1.4.5"reliable.h#define RELIABLE_VERSION_PATCH 4→5RELIABLE_VERSION_MAJOR(1) andRELIABLE_VERSION_MINOR(4) are unchanged.LICENCEand all license prose are untouched (GATE-9).Gate lines
version consistency(.github/workflows/release-check.yml), run locally with the workflow's own sed extraction:(The tag arm of that job is not exercised here — it fires on
refs/tags/*, and it will comparev1.4.5against these two sites when the tag is pushed.)Build and test, CMake Debug with
-DRELIABLE_SANITIZE=ON,cmake --build build --clean-first --parallel(macOS 15, AppleClang):All three tests from #66 are present and green in this tree.
Release notes (draft, Rowan edits)
reliable 1.4.5: a reassembled packet never carries stale heap bytes, and a caller's unterminated endpoint name cannot be over-read
A packet reassembled from fragments is now built in zeroed memory, and an endpoint name the caller never terminated can no longer be read past. Both are from security#26 — items 2 and 3 — and landed together in reliable#66.
The reassembly buffer is allocated through the endpoint's allocator:
allocate_function, the caller's own if one was supplied andreliable_default_allocate_function, a baremalloc, if not. That memory arrives uninitialized, holding whatever the heap last put there. The fix does not bypass the caller's allocator and does not add an allocation —reliable_endpoint_receive_packetstill asks the same allocator for the same buffer, and now runs onememsetover it before any fragment is stored. The length is the one already computed for that allocation:RELIABLE_MAX_PACKET_HEADER_BYTES, plus the fragment count times the endpoint's ownconfig.fragment_size, plus eight. It is bounded by the endpoint's own configuration rather than by anything a peer sends, and it is one memset per reassembly allocation, not one per fragment. As the code stands the delivered bytes could not have contained stale heap: completeness is enforced by the fragment bitmap and every fragment's offset is validated before the copy. This change is about what happens when that stops being true — a future logic error that leaves a hole in the buffer now leaks zeros into the delivered packet instead of the contents of freed memory.test_fragment_reassembly_buffer_zeroedcovers it.reliable_config_t.nameis a fixed array the caller fills, and nothing in the API requires the caller to NUL terminate it.reliable_endpoint_createcopies the config into the endpoint and now forces a terminator onto the last byte of its own copy, so every log that prints the endpoint's name stops inside the array — including the allocation-failure log at create, which now prints that terminated copy rather than the caller's struct. The config checks run before the copy exists and so cannot rely on the terminator: each of the twelve create-time rejection logs now prints the caller's name with a precision,%.*sbounded by the size of the field, soprintfstops at the end of the array instead of reading past it. Before this, a caller who filled the whole name with no terminator had the library read off the end of their struct — adjacent memory disclosed into the log, or a fault.test_endpoint_name_terminatedandtest_config_name_bounded_in_rejection_logcover it.Nothing on the wire changes, no symbol changes, and reassembled bytes are unchanged. Found by an outside security review.
🤖 Generated with Claude Code