From: Johannes Schindelin Date: Thu, 16 Jul 2026 14:27:51 +0000 (+0000) Subject: wincred: prevent silent credential loss when storing OAuth tokens X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f635ab9ab496ad710fec16f3d854e064110d158f;p=thirdparty%2Fgit.git wincred: prevent silent credential loss when storing OAuth tokens 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 Signed-off-by: Junio C Hamano --- 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); }