verbosity: tag matching stops at the terminator

The threaded-video suite's AddressSanitizer lane caught the flush
predicate overreading: rarch_log_tag_wants_flush() compared the tag
with memcmp and the pattern's sizeof, so matching "[WARN]" - seven
bytes with its terminator - against "[ERROR]"'s eight-byte pattern
read one byte past the tag's global. The very first line of any
boot (config load's RARCH_WARN) trips it under ASan; on ordinary
builds it is a silent one-byte overread whose result is correct by
accident, since the compare has already differed by then. The
Android priority mapping carried the identical sized-memcmp pattern
against core-supplied tags of any length, and was the precedent the
predicate copied - both now use strcmp, which stops at the first
difference or terminator and cannot overread either operand.

Verified: the threaded-video harness runs green through the exact
boot path the CI trace aborted in, the log-atomicity harness
(including the flush-durability lane) green three consecutive runs,
the logger-macros suite green in all four configurations, Android
stub syntax pass, C89 gate, full build clean, thread-read audit 0
findings, and the 74-lane compile matrix.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-09-16 11:18:12 +02:00
1 parent 6d88945ae2
commit afd57d615e
1 file changed
+10 -6
+10 -6
View File
@@ -316,10 +316,12 @@ static const char *rarch_log_line_format(char *line, size_t line_size,
* a core-supplied custom tag rides the buffer like INFO. */
static bool rarch_log_tag_wants_flush(const char *tag_v)
{
return memcmp(tag_v, FILE_PATH_LOG_ERROR,
sizeof(FILE_PATH_LOG_ERROR)) == 0
|| memcmp(tag_v, FILE_PATH_LOG_WARN,
sizeof(FILE_PATH_LOG_WARN)) == 0;
/* strcmp, not memcmp with the pattern's sizeof: the tag can be a
* shorter string than the pattern ("[WARN]" against "[ERROR]"'s
* eight bytes), and a sized compare reads past its terminator -
* a one-byte overread AddressSanitizer stops the process for. */
return strcmp(tag_v, FILE_PATH_LOG_ERROR) == 0
|| strcmp(tag_v, FILE_PATH_LOG_WARN) == 0;
}
/* One write - and, for lines that must not wait, one flush - under
@@ -399,9 +401,11 @@ void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap)
int prio = ANDROID_LOG_INFO;
if (tag)
{
if (memcmp(tag, FILE_PATH_LOG_WARN, sizeof(FILE_PATH_LOG_WARN)) == 0)
/* strcmp for the same reason as rarch_log_tag_wants_flush:
* a sized memcmp reads past a shorter tag's terminator. */
if (strcmp(tag, FILE_PATH_LOG_WARN) == 0)
prio = ANDROID_LOG_WARN;
else if (memcmp(tag, FILE_PATH_LOG_ERROR, sizeof(FILE_PATH_LOG_ERROR)) == 0)
else if (strcmp(tag, FILE_PATH_LOG_ERROR) == 0)
prio = ANDROID_LOG_ERROR;
}
__android_log_vprint(prio, FILE_PATH_PROGRAM_NAME, fmt, ap);