From 08e6c4a2da79d7266eb22eec8cf6de3b7c8693f7 Mon Sep 17 00:00:00 2001 From: Petter Reinholdtsen Date: Tue, 16 Aug 2022 06:43:21 +0200 Subject: [PATCH] Make print methods in libnml/rcs/rcs_print.cc handle any size strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite rcs_vprint(), rcs_print() and rcs_print_sys_error() to always print full string and drop use of static fixed size temp string. Also make sure trailing NUL is counted when copying strings into list of last errors. Set output limit to 2^16 to avoid any malloc bombs. This is the warning. Compiling libnml/rcs/rcs_print.cc In file included from /usr/include/string.h:495, from libnml/rcs/rcs_print.cc:21: In function ‘char* strncpy(char*, const char*, size_t)’, inlined from ‘int rcs_vprint(const char*, __va_list_tag*, int)’ at libnml/rcs/rcs_print.cc:311:9: /usr/include/x86_64-linux-gnu/bits/string_fortified.h:106:34: warning: ‘char* __builtin_strncpy(char*, const char*, long unsigned int)’ output may be truncated copying 99 bytes from a string of length 255 [-Wstringop-truncation] 106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest)); | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- src/libnml/rcs/rcs_print.cc | 121 +++++++++++++++++++++++++++--------- 1 file changed, 93 insertions(+), 28 deletions(-) diff --git a/src/libnml/rcs/rcs_print.cc b/src/libnml/rcs/rcs_print.cc index baecec74fcf..66a0f3786b4 100644 --- a/src/libnml/rcs/rcs_print.cc +++ b/src/libnml/rcs/rcs_print.cc @@ -35,6 +35,8 @@ extern "C" { extern "C" double etime(void); #endif +#define MAX_PRINT_LINE (2^16) + LinkedList *rcs_print_list = NULL; char **rcs_lines_table = NULL; void (*rcs_print_notify) () = NULL; @@ -287,15 +289,29 @@ int separate_words(char **_dest, int _max, char *_src) int rcs_vprint(const char *_fmt, va_list _args, int save_string) { - static char temp_string[256]; + char *temp_buffer = NULL; + int retval; + size_t size = 0; + va_list argscopy; if (NULL == _fmt) { return (EOF); } - if (strlen(_fmt) > 200) { /* Might overflow temp_string. */ - return (EOF); + /* Figure out string size */ + va_copy(argscopy, _args); + size_t n = vsnprintf(temp_buffer, size, _fmt, argscopy); + va_end(argscopy); + if (n < 0 || MAX_PRINT_LINE <= n) { /* avoid malloc() bomb */ + return (EOF); + } + temp_buffer = (char*)malloc(n+1); + if (!temp_buffer) { + return (EOF); } - if (EOF == (int) vsnprintf(temp_string, sizeof(temp_string), _fmt, _args)) { + size = n + 1; + + if (size != (size_t)vsnprintf(temp_buffer, size, _fmt, _args)) { + free(temp_buffer); return (EOF); } if (save_string) { @@ -308,9 +324,11 @@ int rcs_vprint(const char *_fmt, va_list _args, int save_string) } last_error_buf_filled++; last_error_buf_filled %= 4; - strncpy(last_error_bufs[last_error_buf_filled], temp_string, 99); + rtapi_strlcpy(last_error_bufs[last_error_buf_filled], temp_buffer, 100); } - return (rcs_fputs(temp_string)); + retval = rcs_fputs(temp_buffer); + free(temp_buffer); + return (retval); } int rcs_puts(const char *_str) @@ -431,16 +449,36 @@ int set_rcs_print_file(char *_file_name) int rcs_print(const char *_fmt, ...) { - static char temp_buffer[400]; + char *temp_buffer = NULL; int retval; - va_list args; + va_list args, argscopy; + size_t size = 0; + + if (NULL == _fmt) { + return (EOF); + } va_start(args, _fmt); - retval = vsnprintf(temp_buffer, sizeof(temp_buffer), _fmt, args); + + /* Figure out string size */ + va_copy(argscopy, args); + size_t n = vsnprintf(temp_buffer, size, _fmt, argscopy); + va_end(argscopy); + if (n < 0 || MAX_PRINT_LINE <= n) { /* avoid malloc() bomb */ + return (EOF); + } + temp_buffer = (char*)malloc(n+1); + if (!temp_buffer) { + return (EOF); + } + size = n + 1; + retval = vsnprintf(temp_buffer, size, _fmt, args); va_end(args); - if (retval == (EOF)) { - return EOF; + if (size != (size_t)retval) { + free(temp_buffer); + return (EOF); } retval = rcs_fputs(temp_buffer); + free(temp_buffer); return (retval); } @@ -510,23 +548,34 @@ void clear_rcs_print_flag(long flag_to_clear) int rcs_print_sys_error(int error_source, const char *_fmt, ...) { - static char temp_string[256]; - static char message_string[512]; - va_list args; - int r; + static char *temp_buffer = NULL; + static char *message_string = NULL; + va_list args, argscopy; + size_t size = 0; + size_t msize = 0; + int retval; if (NULL == _fmt) { return (EOF); } - if (strlen(_fmt) > 200) { /* Might overflow temp_string. */ - return (EOF); - } - va_start(args, _fmt); - r = vsnprintf(temp_string, sizeof(temp_string), _fmt, args); + + /* Figure out string size */ + va_copy(argscopy, args); + retval = vsnprintf(temp_buffer, size, _fmt, argscopy); + va_end(argscopy); + if (retval < 0 || MAX_PRINT_LINE <= retval) { /* avoid malloc() bomb */ + return (EOF); + } + temp_buffer = (char*)malloc(retval+1); + if (!temp_buffer) { + return (EOF); + } + size = retval + 1; + retval = vsnprintf(temp_buffer, size, _fmt, args); va_end(args); - if (r < 0) { + if (size != (size_t)retval) { return EOF; } @@ -537,22 +586,38 @@ int rcs_print_sys_error(int error_source, const char *_fmt, ...) rcs_errors_printed++; if (max_rcs_errors_to_print <= rcs_errors_printed && max_rcs_errors_to_print >= 0) { + free(temp_buffer); return (EOF); } switch (error_source) { case ERRNO_ERROR_SOURCE: - snprintf(message_string, sizeof(message_string), - "%s %d %s\n", temp_string, errno, - strerror(errno)); - rcs_puts(message_string); - break; + /* Figure out string size */ + retval = snprintf(message_string, msize, + "%s %d %s\n", temp_buffer, errno, strerror(errno)); + if (retval < 0 || MAX_PRINT_LINE <= retval) { /* avoid malloc() bomb */ + return (EOF); + } + message_string = (char*)malloc(retval+1); + if (!message_string) { + return (EOF); + } + msize = retval + 1; + retval = snprintf(message_string, msize, + "%s %d %s\n", temp_buffer, errno, strerror(errno)); + if (msize != (size_t)retval) { + return EOF; + } + rcs_puts(message_string); + free(message_string); + break; default: - rcs_puts(temp_string); + rcs_puts(temp_buffer); break; } - return (strlen(temp_string)); + free(temp_buffer); + return (size - 1); /* string length without trailing NUL */ } #ifdef rcs_print_error