pe: null-terminate authenticode digest/thumbprint hex buffers (#2221)

digest_ascii buffers in _process_authenticode() and thumbprint_ascii in
write_certificate() are filled by a sprintf loop that writes exactly
len*2 hex chars but never sets the trailing byte, even though every
buffer is sized len*2+1 to hold it. yr_set_string() calls strlen() on
the result before copying, so the string used to actually run past the
hex digits into whatever uninitialized stack/heap byte follows until
it happens to hit a zero.

Same bug shape already fixed correctly for imphash in this same file
(pe_get_imphash sets digest_ascii[YR_MD5_LEN * 2] = '\''\0'\'' after its
loop) - this applies the same fix to the four authenticode digest sites
and the certificate thumbprint site.

Fixes #2176. The failing test (test-pe.c, pe.signatures[0].thumbprint
compared against a fixed hex string) reads one of the buffers this
touches, which explains the platform/compiler-dependent flakiness
reported there (stack contents differ across Rocky 8 vs 9).
This commit is contained in:
Cole Munz
2026-07-06 09:44:06 +02:00
committed by GitHub
parent 8a5a88e463
commit fa372ebb98
+5
View File
@@ -1754,6 +1754,7 @@ static void pe_parse_exports(PE* pe)
char thumbprint_ascii[YR_SHA1_LEN * 2 + 1]; \
for (int j = 0; j < cert->sha1.len; ++j) \
sprintf(thumbprint_ascii + (j * 2), "%02x", cert->sha1.data[j]); \
thumbprint_ascii[cert->sha1.len * 2] = '\0'; \
\
yr_set_string( \
(char*) thumbprint_ascii, pe->object, fmt ".thumbprint", __VA_ARGS__); \
@@ -1820,6 +1821,7 @@ void _process_authenticode(
char* digest_ascii = yr_malloc(authenticode->digest.len * 2 + 1);
for (int j = 0; j < authenticode->digest.len; ++j)
sprintf(digest_ascii + (j * 2), "%02x", authenticode->digest.data[j]);
digest_ascii[authenticode->digest.len * 2] = '\0';
yr_set_string(
digest_ascii, pe->object, "signatures[%i].digest", *sig_count);
@@ -1832,6 +1834,7 @@ void _process_authenticode(
for (int j = 0; j < authenticode->file_digest.len; ++j)
sprintf(
digest_ascii + (j * 2), "%02x", authenticode->file_digest.data[j]);
digest_ascii[authenticode->file_digest.len * 2] = '\0';
yr_set_string(
digest_ascii, pe->object, "signatures[%i].file_digest", *sig_count);
@@ -1884,6 +1887,7 @@ void _process_authenticode(
char* digest_ascii = yr_malloc(signer->digest.len * 2 + 1);
for (int j = 0; j < signer->digest.len; ++j)
sprintf(digest_ascii + (j * 2), "%02x", signer->digest.data[j]);
digest_ascii[signer->digest.len * 2] = '\0';
yr_set_string(
digest_ascii,
@@ -1950,6 +1954,7 @@ void _process_authenticode(
char* digest_ascii = yr_malloc(counter->digest.len * 2 + 1);
for (int j = 0; j < counter->digest.len; ++j)
sprintf(digest_ascii + (j * 2), "%02x", counter->digest.data[j]);
digest_ascii[counter->digest.len * 2] = '\0';
yr_set_string(
digest_ascii,