[monitoring-plugins] check_icmp: Fix parsing of single-char threshold

Holger Weiss git at monitoring-plugins.org
Wed Jul 1 13:20:13 CEST 2026


 Module: monitoring-plugins
 Branch: master
 Commit: a675995b19a6315f1b033a7c1ca980b5fbdc408d
 Author: Holger Weiss <holger at zedat.fu-berlin.de>
   Date: Tue Jun 30 15:58:09 2026 +0200
    URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=a675995b

check_icmp: Fix parsing of single-char threshold

The threshold parser starts a pointer at the last character of the
string and walks it backwards until it reaches the second character.
This assumes the string is at least two characters long.  For a
single-character threshold such as "-w 1" or "-c 1", the pointer
underflows past the start of the string and keeps dereferencing memory
out of bounds.

Beyond the out-of-bounds reads, an out-of-bounds write can occur if a
stray '%' or ',' byte happens to turn up while scanning backwards.  In
that case, the parser writes a NUL byte at that out-of-bounds address
(the ',' case additionally re-reads forward from there via strtoul(3)).

Only run the descending scan when the string has at least two
characters, leaving the behaviour for all valid thresholds unchanged.

Reported-by: Christopher Kreft <Email at ChristopherKreft.de>

---

 plugins-root/check_icmp.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index f3c83ee0..8f5c1fe4 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -1926,18 +1926,21 @@ static get_threshold_wrapper get_threshold(char *str, check_icmp_threshold thres
 	}
 
 	/* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */
-	bool is_at_last_char = false;
-	char *tmp = &str[strlen(str) - 1];
-	while (tmp != &str[1]) {
-		if (*tmp == '%') {
-			*tmp = '\0';
-		} else if (*tmp == ',' && is_at_last_char) {
-			*tmp = '\0'; /* reset it so get_timevar(str) works nicely later */
-			result.threshold.pl = (unsigned char)strtoul(tmp + 1, NULL, 0);
-			break;
+	size_t len = strlen(str);
+	if (len >= 2) {
+		bool is_at_last_char = false;
+		char *tmp = &str[len - 1];
+		while (tmp != &str[1]) {
+			if (*tmp == '%') {
+				*tmp = '\0';
+			} else if (*tmp == ',' && is_at_last_char) {
+				*tmp = '\0'; /* reset it so get_timevar(str) works nicely later */
+				result.threshold.pl = (unsigned char)strtoul(tmp + 1, NULL, 0);
+				break;
+			}
+			is_at_last_char = true;
+			tmp--;
 		}
-		is_at_last_char = true;
-		tmp--;
 	}
 
 	get_timevar_wrapper parsed_time = get_timevar(str);



More information about the Commits mailing list