From: Johannes Schindelin <johannes.schindelin@gmx.de>
When `git credential approve` hands the wincred helper a password together with an `oauth_refresh_token`, the OAuth branch of `store_credential()` writes one WCHAR past the allocation while formatting both fields into a single `CredentialBlob`. On Windows this trips heap verification and tears the helper down with status `0xC0000374`; `approve` masks the failure, so the credential the user meant to save never reaches `CredWriteW()` and the next session prompts for it again.
The bug has the same shape as the one fixed in the previous commit: the allocation leaves no room for the terminating NUL, and the `sizeOfBuffer` argument to `_snwprintf_s()` is a byte count where the API expects a WCHAR count, which lets the safe-CRT runtime write the terminator out of bounds.
Apply the same remedy d22a488482 (wincred: avoid memory corruption, 2025-11-17) applied in `get_credential()`: allocate `(wlen + 1) * sizeof(WCHAR)` bytes and pass `wlen + 1` as the destination capacity in WCHARs.
This closes the second of the two heap writes tracked under GHSA-rxqw-wxqg-g7hw.
Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
contrib/credential/wincred/git-credential-wincred.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Show changes to contrib/credential/wincred/git-credential-wincred.c +2 −2
diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c
index 190bbccdf9..22eb27ca31 100644
--- a/contrib/credential/wincred/git-credential-wincred.c
+++ b/contrib/credential/wincred/git-credential-wincred.c
@@ -208,8 +208,8 @@ static void store_credential(void)
if (oauth_refresh_token) {
wlen = _scwprintf(L"%s\r\noauth_refresh_token=%s", password, oauth_refresh_token);
- secret = xmalloc(sizeof(WCHAR) * wlen);
- _snwprintf_s(secret, sizeof(WCHAR) * wlen, wlen, L"%s\r\noauth_refresh_token=%s", password, oauth_refresh_token);
+ secret = xmalloc((wlen + 1) * sizeof(WCHAR));
+ _snwprintf_s(secret, wlen + 1, wlen, L"%s\r\noauth_refresh_token=%s", password, oauth_refresh_token);
} else {
secret = _wcsdup(password);
}