-
Type:
Problem report
-
Resolution: Unresolved
-
Priority:
Trivial
-
None
-
Affects Version/s: 7.4.16
-
Component/s: Agent (G)
-
None
Description
In src/libs/zbxsysinfo/win32/software.c (lines 46-84), the helper function join_nonempty_strs() calculates the total length of non-empty strings and delimiters in str_size, but forgets to add + 1 for the terminating NUL character ('\0') when allocating memory with zbx_malloc() and passing the buffer size to zbx_snprintf():
static char *join_nonempty_strs(const char **strs, size_t strs_count, const char *delimiter) { ... for (size_t i = 0; i < strs_count; i++) { if (NULL != strs[i] && '\0' != strs[i][0]) str_size += strlen(strs[i]) + delimiter_len; } if (delimiter_len <= str_size) str_size -= delimiter_len; res_str = zbx_malloc(NULL, str_size * sizeof(char)); res_str[0] = '\0'; ... offset += zbx_snprintf(res_str + offset, str_size - offset, "%s", strs[i]);
Impact
- Last character truncation: When one or more strings are non-empty, str_size equals the exact sum of strlen() values without space for the NUL terminator. Because zbx_snprintf(res_str + offset, str_size - offset, ...) always reserves 1 byte for '\0', the very last character of the joined architecture string in SYSTEM_SW_ARCH() is silently truncated (e.g., "x86, x64" becomes "x86, x6").
- Zero-byte allocation write: If all entries in strs are NULL or empty (""), str_size remains 0. zbx_malloc(NULL, 0) allocates a 0-byte buffer, and res_str[0] = '\0'; immediately performs a 1-byte out-of-bounds write.
Suggested Patch
Allocate str_size + 1 bytes and pass str_size + 1 - offset to zbx_snprintf():
Unable to find source-code formatter for language: diff. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
--- a/src/libs/zbxsysinfo/win32/software.c +++ b/src/libs/zbxsysinfo/win32/software.c @@ -60,7 +60,8 @@ static char *join_nonempty_strs(const char **strs, size_t strs_count, const char if (delimiter_len <= str_size) str_size -= delimiter_len; - res_str = zbx_malloc(NULL, str_size * sizeof(char)); + str_size++; + res_str = zbx_malloc(NULL, str_size * sizeof(char)); res_str[0] = '\0'; for (size_t i = 0; i < strs_count; i++)