]> granicus.if.org Git - procps-ng/commitdiff
top: Prevent out-of-bounds writes in PUFF().
authorQualys Security Advisory <qsa@qualys.com>
Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)
committerCraig Small <csmall@enc.com.au>
Fri, 18 May 2018 21:33:15 +0000 (07:33 +1000)
This patch prevents three problems:

1/ Because snprintf() returns "the number of characters (excluding the
terminating null byte) which would have been written to the final string
if enough space had been available", _eol may point past the end of _str
and write out-of-bounds (in Batch mode).

2/ _eol is never checked against _str, so "while (*(--_eol) == ' ');"
may point _eol below _str and write out-of-bounds (in Batch mode).

3/ Sanity-check Pseudo_row to protect the strcpy().

top/top.h

index 02e387491ba5f9d9007574936c22e74140cb5d69..046fc87906b89bfb2cf3aa29ae41239def362b6a 100644 (file)
--- a/top/top.h
+++ b/top/top.h
@@ -547,10 +547,11 @@ typedef struct WIN_t {
                . subject to optimization, thus MAY be discarded */
 #define PUFF(fmt,arg...) do { \
       char _str[ROWMAXSIZ], *_eol; \
-      _eol = _str + snprintf(_str, sizeof(_str), fmt, ## arg); \
+      const int _len = snprintf(_str, sizeof(_str), fmt, ## arg); \
+      _eol = _str + (_len < 0 ? 0 : (size_t)_len >= sizeof(_str) ? sizeof(_str)-1 : (size_t)_len); \
       if (Batch) { \
-         while (*(--_eol) == ' '); *(++_eol) = '\0'; putp(_str); } \
-      else { \
+         while (_eol > _str && _eol[-1] == ' ') _eol--; *_eol = '\0'; putp(_str); } \
+      else if (Pseudo_row >= 0 && Pseudo_row < Screen_rows) { \
          char *_ptr = &Pseudo_screen[Pseudo_row * ROWMAXSIZ]; \
          if (Pseudo_row + 1 < Screen_rows) ++Pseudo_row; \
          if (!strcmp(_ptr, _str)) putp("\n"); \