fix: ParseScpCommand leaks scpBasePathDynamic on repeated -t/-f#1125
Open
MarkAtwood wants to merge 1 commit into
Open
fix: ParseScpCommand leaks scpBasePathDynamic on repeated -t/-f#1125MarkAtwood wants to merge 1 commit into
MarkAtwood wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a memory leak in ParseScpCommand() (SCP command parsing) where repeated -t/-f options could overwrite ssh->scpBasePathDynamic without freeing the prior allocation, causing per-connection lifetime leaks on peer-controlled commands.
Changes:
- Free
ssh->scpBasePathDynamicbefore re-allocating it in the-tparsing branch. - Free
ssh->scpBasePathDynamicbefore re-allocating it in the-fparsing branch.
Comments suppressed due to low confidence (2)
src/wolfscp.c:1526
- After freeing scpBasePathDynamic, ssh->scpBasePath can still point at the freed buffer. If the subsequent WMALLOC fails (or if the option has no trailing path and the later assignment isn’t hit), the session may retain a dangling scpBasePath pointer. Clear scpBasePath when freeing and set it to the newly allocated buffer immediately after allocation/memset so it always points at valid storage.
This issue also appears on line 1547 of the same file.
if (ssh->scpBasePathDynamic != NULL) {
WFREE(ssh->scpBasePathDynamic, ssh->ctx->heap,
DYNTYPE_BUFFER);
ssh->scpBasePathDynamic = NULL;
}
ssh->scpBasePathDynamic = (char*)WMALLOC(
ssh->scpBasePathSz,
ssh->ctx->heap, DYNTYPE_BUFFER);
if (ssh->scpBasePathDynamic == NULL) {
return WS_MEMORY_E;
}
WMEMSET(ssh->scpBasePathDynamic, 0, ssh->scpBasePathSz);
src/wolfscp.c:1558
- Same as the -t case: after freeing scpBasePathDynamic, ssh->scpBasePath may still reference freed memory. Clearing scpBasePath on free and setting it to the newly allocated buffer avoids leaving a dangling pointer behind if allocation fails or if later code paths don’t reassign scpBasePath.
if (ssh->scpBasePathDynamic != NULL) {
WFREE(ssh->scpBasePathDynamic, ssh->ctx->heap,
DYNTYPE_BUFFER);
ssh->scpBasePathDynamic = NULL;
}
ssh->scpBasePathDynamic = (char*)WMALLOC(
ssh->scpBasePathSz,
ssh->ctx->heap, DYNTYPE_BUFFER);
if (ssh->scpBasePathDynamic == NULL) {
return WS_MEMORY_E;
}
WMEMSET(ssh->scpBasePathDynamic, 0, ssh->scpBasePathSz);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
Bug
ParseScpCommand()(src/wolfscp.c) allocatesssh->scpBasePathDynamicin boththe
-tand-fcases and assigns straight to the struct member withoutfreeing a previous allocation. The option scan does not consume the copied
remainder of the command, so a peer command that repeats the direction option
(
scp -t a -t b,scp -f a -f b) re-enters the case, allocates again, andoverwrites the pointer, leaking the earlier buffer. The command string is
peer-controlled (
wolfSSH_GetSessionCommand). The single teardown free(internal.c) releases only the final pointer, so every prior allocation leaks
for the connection lifetime.
Fix
Free and clear
ssh->scpBasePathDynamicbefore each (re)allocation.Verification
Built
--enable-allagainst wolfSSL master; compiles clean.Reported by static analysis (Fenrir finding F-6813).