Don't overrun in error prints

vsprintf returns the amount it would have written if the buffer had been
big enough, but we used that value directly when outputting, thus
overrunning memory and dumping stack contents.

Indicate truncation by inserting an ellipsis and newline. Slightly
increase the buffer size, so that we don't slightly decrease the maximum
printable characters because of the ellipsis insertion.

Partially addresses https://github.com/ARMmbed/mbed-os/issues/6850 by
forcing a newline when truncation happens - often truncation will drop a
newline and prevent a flush.
pull/8076/head
Kevin Bracey 2018-09-11 11:40:23 +03:00
parent c989845d5a
commit 2df322c43d
1 changed files with 23 additions and 17 deletions

View File

@ -56,25 +56,31 @@ void mbed_error_printf(const char *format, ...)
void mbed_error_vprintf(const char *format, va_list arg)
{
#define ERROR_BUF_SIZE (128)
core_util_critical_section_enter();
char buffer[ERROR_BUF_SIZE];
int size = vsnprintf(buffer, ERROR_BUF_SIZE, format, arg);
if (size > 0) {
#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES || MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES
char stdio_out_prev = '\0';
for (int i = 0; i < size; i++) {
if (buffer[i] == '\n' && stdio_out_prev != '\r') {
const char cr = '\r';
write(STDERR_FILENO, &cr, 1);
}
write(STDERR_FILENO, &buffer[i], 1);
stdio_out_prev = buffer[i];
}
#else
write(STDERR_FILENO, buffer, size);
#endif
char buffer[132];
int size = vsnprintf(buffer, sizeof buffer, format, arg);
if (size >= sizeof buffer) {
/* Output was truncated - indicate by overwriting last 4 bytes of buffer
* with ellipsis and newline.
* (Note that although vsnprintf always leaves a NUL terminator, we
* don't need a terminator and can use the entire buffer)
*/
memcpy(&buffer[sizeof buffer - 4], "...\n", 4);
size = sizeof buffer;
}
#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES || MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES
char stdio_out_prev = '\0';
for (int i = 0; i < size; i++) {
if (buffer[i] == '\n' && stdio_out_prev != '\r') {
const char cr = '\r';
write(STDERR_FILENO, &cr, 1);
}
write(STDERR_FILENO, &buffer[i], 1);
stdio_out_prev = buffer[i];
}
#else
write(STDERR_FILENO, buffer, size);
#endif
core_util_critical_section_exit();
}