Unchecked PSS salt-length conversion reaches a near-SIZE_MAX write
RSA-PSS signing parses the bounded salt-length atom without checking its length, parse endpoint, range, or errno, stores it as unsigned int, and passes it to an encoder taking int. On mainstream two's-complement ABIs, 4294967295 becomes -1; mixed signed/unsigned arithmetic then allocates a small buffer before _gcry_randomize receives SIZE_MAX, causing deterministic heap corruption through public gcry_pk_sign.
Vulnerable code
cipher/pubkey-util.c, _gcry_pk_util_data_to_mpi:
c
s = sexp_nth_data (list, 1, &n);
if (!s)
{
rc = GPG_ERR_NO_OBJ;
goto leave;
}
ctx->saltlen = (unsigned int)strtoul (s, NULL, 10);cipher/rsa-common.c, _gcry_rsa_pss_encode:
c
_gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
int saltlen, int hashed_already,
const unsigned char *value, size_t valuelen,
const void *random_override)c buflen = 8 + hlen + saltlen + (emlen - hlen - 1); buf = xtrymalloc (buflen);
c
_gcry_randomize (salt, saltlen, GCRY_STRONG_RANDOM);Why it matters
Services that sign attacker-influenced PSS S-expressions can be terminated and have adjacent heap objects overwritten with random bytes. The public-API ASan reproducer observed a write just beyond a 134-byte allocation, with the call chain ending at _gcry_rsa_pss_encode. FIPS policy may reject oversized salts, but ordinary mode reaches the write; the verification path's separate 16384-byte bound does not protect signing.
Proposed fix
Parse exactly the n atom bytes via a NUL-terminated temporary, with errno = 0, an end pointer, and rejection of empty, trailing, negative, or out-of-range input. Use size_t consistently in the encoder, require saltlen <= emlen - hlen - 2 after checked subtraction, and check every allocation sum. Add regressions for INT_MAX, UINT_MAX, decimal overflow, embedded/trailing bytes, and the modulus-derived boundary.