Skip to content

fix: free initial signature buffer before realloc in sign()#98

Closed
toddr-bot wants to merge 2 commits into
cpan-authors:mainfrom
toddr-bot:koan.toddr.bot/fix-sign-double-alloc-leak
Closed

fix: free initial signature buffer before realloc in sign()#98
toddr-bot wants to merge 2 commits into
cpan-authors:mainfrom
toddr-bot:koan.toddr.bot/fix-sign-double-alloc-leak

Conversation

@toddr-bot
Copy link
Copy Markdown
Contributor

@toddr-bot toddr-bot commented Mar 14, 2026

What

Free the initial signature buffer before reallocating on the OpenSSL 3.x code path in sign().

Why

CHECK_NEW at RSA.xs:987 allocates a signature buffer sized by EVP_PKEY_get_size(). The OpenSSL 3.x path then queries the actual needed size via EVP_PKEY_sign(ctx, NULL, &signature_length, ...) and allocates a new buffer with Newx() — but the original pointer is overwritten without freeing, leaking memory on every sign() call.

How

Added Safefree(signature) before the Newx() call. The pre-3.x #else path is unaffected — it uses the initial buffer directly with RSA_sign().

Also removed the stale commented-out OPENSSL_malloc line.

Testing

  • Full test suite passes (318 tests, 10 files)
  • Build environment has OpenSSL 1.1.1k so the 3.x path isn't exercised at runtime, but the fix is straightforward: free-before-realloc

🤖 Generated with Claude Code


Quality Report

Changes: 1 file changed, 1 insertion(+), 1 deletion(-)

Code scan: clean

Tests: passed (OK)

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

@Koan-Bot
Copy link
Copy Markdown
Contributor

PR Review — fix: free initial signature buffer before realloc in sign()

The core fix (freeing the initial buffer before reallocation) is correct and addresses the memory leak described in the PR. However, the current main branch has already been restructured to eliminate this leak entirely by moving CHECK_NEW inside the #else block and using THROW/goto err for the 3.x path. This PR will conflict on merge and is effectively already superseded. Additionally, the Newx call uses char instead of UNSIGNED_CHAR, inconsistent with the variable declaration. Recommend rebasing onto current main and confirming the fix is still needed (it likely isn't).


🟡 Important

1. Fix is correct but current main has already restructured this code (RSA.xs, L1013)
The Safefree(signature) before Newx() correctly fixes the leak caused by CHECK_NEW allocating a buffer before the #if block, which gets overwritten in the 3.x path.

However, note that main has already been restructured: the CHECK_NEW allocation was moved inside the #else (pre-3.x) branch, and the 3.x path now uses THROW/goto err with a single Newx allocation. This means:

  1. The leak no longer exists on current main.
  2. This PR will likely conflict on merge.

If the intent is to land this on the current main, the PR needs to be rebased. If it targets an older baseline, the fix itself is sound.

Safefree(signature);
Newx(signature, signature_length, char);

2. CHECK_OPEN_SSL after Newx leaks signature on failure (RSA.xs, L1010-1015)
If CHECK_OPEN_SSL(signature) or the subsequent CHECK_OPEN_SSL(EVP_PKEY_sign(...)) triggers croak(), the newly allocated signature buffer is leaked. The current main addresses this by using the THROW/goto err pattern with cleanup at the err: label. Since this PR keeps the CHECK_OPEN_SSL pattern (which croaks immediately), error-path leaks remain. This is a pre-existing issue rather than a regression from this PR, but worth noting since the fix is in scope of the same function.

CHECK_OPEN_SSL(signature);
// ... EVP_PKEY_sign call ...
// if croak() fires, signature is leaked

🟢 Suggestions

1. Use UNSIGNED_CHAR type consistently with declaration (RSA.xs, L1013-1014)
The signature variable is declared as UNSIGNED_CHAR *signature (line ~1017 in the original), but Newx(signature, signature_length, char) allocates as char. This should be Newx(signature, signature_length, UNSIGNED_CHAR) for type consistency. Current main already uses UNSIGNED_CHAR in the equivalent Newx call.

Newx(signature, signature_length, char);

Checklist


Summary

The core fix (freeing the initial buffer before reallocation) is correct and addresses the memory leak described in the PR. However, the current main branch has already been restructured to eliminate this leak entirely by moving CHECK_NEW inside the #else block and using THROW/goto err for the 3.x path. This PR will conflict on merge and is effectively already superseded. Additionally, the Newx call uses char instead of UNSIGNED_CHAR, inconsistent with the variable declaration. Recommend rebasing onto current main and confirming the fix is still needed (it likely isn't).


Automated review by Kōan

@atoomic
Copy link
Copy Markdown
Collaborator

atoomic commented Mar 16, 2026

@toddr-bot rebase

toddr-bot and others added 2 commits March 16, 2026 23:42
On the OpenSSL 3.x path, sign() first allocates a signature buffer via
CHECK_NEW (line 987), then queries the actual required size with
EVP_PKEY_sign(NULL), then overwrites the pointer with Newx() without
freeing the first allocation. This leaks the initial buffer on every
call to sign().

Add Safefree(signature) before the Newx() to release the first
allocation. The pre-3.x path is unaffected as it uses the initial
buffer directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@toddr-bot
Copy link
Copy Markdown
Contributor Author

Rebase: fix: free initial signature buffer before realloc in sign()

Branch koan.toddr.bot/fix-sign-double-alloc-leak rebased onto main and force-pushed.

Review feedback was analyzed and applied.

Actions

  • Resolved merge conflicts (1 round(s))
  • Rebased koan.toddr.bot/fix-sign-double-alloc-leak onto upstream/main
  • Applied review feedback
  • Force-pushed koan.toddr.bot/fix-sign-double-alloc-leak to origin

Automated by Kōan

@toddr-bot toddr-bot force-pushed the koan.toddr.bot/fix-sign-double-alloc-leak branch from 6bfea0d to 2c05bed Compare March 16, 2026 23:43
@timlegge
Copy link
Copy Markdown
Member

@toddr-bot Empty PR - Closing

@timlegge timlegge closed this Mar 17, 2026
@toddr-bot
Copy link
Copy Markdown
Contributor Author

❌ Permission denied. Only users with write access can trigger bot commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants