[monitoring-plugins] check_{hpjd,real}: Replace sprintf with snprintf ...

GitHub git at monitoring-plugins.org
Mon Oct 19 10:20:13 CEST 2026


    Module: monitoring-plugins
    Branch: master
    Commit: f7588c9f976607ef32d149949eeafd504070b8b9
    Author: Alvar <post at 0x21.biz>
 Committer: GitHub <noreply at github.com>
      Date: Mon Oct 19 08:10:26 2026 +0000
       URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=f7588c9f

check_{hpjd,real}: Replace sprintf with snprintf (#2372)

Replace potentially dangerous sprintf calls in check_hpjd and check_real
with safer snprintf calls. Some of those would allow an overflow.

OpenBSD's ld, ld.lld(1), produces some warnings for potentially
dangerous functions, like sprintf. Today I decided to follow those for
sprintf and found at least one stack overflow via command line arguments
for check_hpjd and a potential one for check_real.

  ld: warning: check_hpjd.c:88(check_hpjd.o:(main)): warning: sprintf() is often misused, please use snprintf()

For check_hpjd, the '-C' flag originally had no limit.

  $ egdb --args ./check_hpjd -C $(yes | head -n 5000 | tr -d '\n') -H example.com
  [...]

  Starting program: [...]/plugins/check_hpjd -C y[...]y -H example.com
  [Detaching after fork from child process 424]

  Program received signal SIGSEGV, Segmentation fault.
  strlen () at /usr/src/lib/libc/arch/amd64/string/strlen.S:154
  154             movq    (%rax),%rdx             /* first data in high bytes */
  (gdb) bt
  #0  strlen () at /usr/src/lib/libc/arch/amd64/string/strlen.S:154
  #1  0x0000033d35778451 in __vfprintf (fp=0x76c6593833b0, fmt0=0x33ab0f340e8 "%s : Timeout from host %s\n", ap=0x76c659383650) at /usr/src/lib/libc/stdio/vfprintf.c:887
  #2  0x0000033d357d5d2b in _libc_vasprintf (str=0x76c659387c98, fmt=0x33ab0f340e8 "%s : Timeout from host %s\n", ap=0x76c659383650) at /usr/src/lib/libc/stdio/vasprintf.c:39
  #3  0x0000033ab0f39fb4 in mopl_utils_xvasprintf (strp=0x76c659387c98, fmt=0x1 <error: Cannot access memory at address 0x1>, ap=<optimized out>) at utils.c:349
  #4  mopl_utils_xasprintf (strp=0x76c659387c98, fmt=0x1 <error: Cannot access memory at address 0x1>) at utils.c:360
  #5  0x0000033ab0f39457 in main (argc=2038004089, argv=<optimized out>) at check_hpjd.c:216

  (gdb) break check_hpjd.c:216
  Breakpoint 1 at 0x33ab0f3943a: file check_hpjd.c, line 216.
  (gdb) run
  The program being debugged has been started already.
  Start it from the beginning? (y or n) y
  Starting program: [...]/plugins/check_hpjd -C y[...]y -H example.com
  [Detaching after fork from child process 25139]

  Breakpoint 1, main (argc=2038004089, argv=<optimized out>) at check_hpjd.c:216
  216                     mopl_utils_xasprintf(&errmsg, "%s : Timeout from host %s\n", errmsg, config.address);
  (gdb) print config
  $1 = {address = 0x7979797979797979 <error: Cannot access memory at address 0x7979797979797979>, community = <optimized out>, port = <optimized out>, check_paper_out = <optimized out>}

The faulty 0x7979797979797979 address are 'y's; the '-C' payload.

---

 plugins/check_hpjd.c | 21 ++++++++++++---------
 plugins/check_real.c | 21 ++++++++++++++-------
 2 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/plugins/check_hpjd.c b/plugins/check_hpjd.c
index fa2f4355..e942d480 100644
--- a/plugins/check_hpjd.c
+++ b/plugins/check_hpjd.c
@@ -85,16 +85,19 @@ int main(int argc, char **argv) {
 	char query_string[512];
 	/* removed ' 2>1' at end of command 10/27/1999 - EG */
 	/* create the query string */
-	sprintf(query_string, "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0",
-			HPJD_LINE_STATUS, HPJD_PAPER_STATUS, HPJD_INTERVENTION_REQUIRED,
-			HPJD_GD_PERIPHERAL_ERROR, HPJD_GD_PAPER_JAM, HPJD_GD_PAPER_OUT, HPJD_GD_TONER_LOW,
-			HPJD_GD_PAGE_PUNT, HPJD_GD_MEMORY_OUT, HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT,
-			HPJD_GD_STATUS_DISPLAY);
+	snprintf(query_string, sizeof(query_string),
+			 "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0", HPJD_LINE_STATUS,
+			 HPJD_PAPER_STATUS, HPJD_INTERVENTION_REQUIRED, HPJD_GD_PERIPHERAL_ERROR,
+			 HPJD_GD_PAPER_JAM, HPJD_GD_PAPER_OUT, HPJD_GD_TONER_LOW, HPJD_GD_PAGE_PUNT,
+			 HPJD_GD_MEMORY_OUT, HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY);
 
 	/* get the command to run */
 	char command_line[1024];
-	sprintf(command_line, "%s -OQa -m : -v 1 -c %s %s:%u %s", PATH_TO_SNMPGET, config.community,
-			config.address, config.port, query_string);
+	int l = snprintf(command_line, sizeof(command_line), "%s -OQa -m : -v 1 -c %s %s:%u %s",
+					 PATH_TO_SNMPGET, config.community, config.address, config.port, query_string);
+	if (l >= sizeof(command_line)) {
+		mopl_utils_usage4(_("Command arguments too long"));
+	}
 
 	/* run the command */
 	child_process = mopl_popen_spopen(command_line);
@@ -140,7 +143,7 @@ int main(int argc, char **argv) {
 
 		if (temp_buffer == NULL && line < 13) {
 			result = STATE_UNKNOWN;
-			strcpy(errmsg, input_buffer);
+			strncpy(errmsg, input_buffer, MAX_INPUT_BUFFER);
 		} else {
 			switch (line) {
 			case 1: /* 1st line should contain the line status */
@@ -198,7 +201,7 @@ int main(int argc, char **argv) {
 		if (input_buffer[strlen(input_buffer) - 1] == '\n') {
 			input_buffer[strlen(input_buffer) - 1] = 0;
 		}
-		sprintf(errmsg, "%s", input_buffer);
+		snprintf(errmsg, MAX_INPUT_BUFFER, "%s", input_buffer);
 	}
 
 	/* close stderr */
diff --git a/plugins/check_real.c b/plugins/check_real.c
index 36ee1876..e4539905 100644
--- a/plugins/check_real.c
+++ b/plugins/check_real.c
@@ -108,7 +108,11 @@ int main(int argc, char **argv) {
 
 	/* send the OPTIONS request */
 	char send_buffer[MAX_INPUT_BUFFER];
-	sprintf(send_buffer, "OPTIONS rtsp://%s:%d RTSP/1.0\r\n", config.host_name, config.server_port);
+	int l = snprintf(send_buffer, MAX_INPUT_BUFFER, "OPTIONS rtsp://%s:%d RTSP/1.0\r\n",
+					 config.host_name, config.server_port);
+	if (l >= MAX_INPUT_BUFFER) {
+		mopl_utils_usage4(_("Command arguments too long"));
+	}
 	ssize_t sent_bytes = send(socket, send_buffer, strlen(send_buffer), 0);
 	if (sent_bytes == -1) {
 		mopl_utils_xasprintf(&sc_send.output, _("Sending options to %s failed"), config.host_name);
@@ -118,7 +122,7 @@ int main(int argc, char **argv) {
 	}
 
 	/* send the header sync */
-	sprintf(send_buffer, "CSeq: 1\r\n");
+	snprintf(send_buffer, MAX_INPUT_BUFFER, "CSeq: 1\r\n");
 	sent_bytes = send(socket, send_buffer, strlen(send_buffer), 0);
 	if (sent_bytes == -1) {
 		mopl_utils_xasprintf(&sc_send.output, _("Sending header sync to %s failed"),
@@ -129,7 +133,7 @@ int main(int argc, char **argv) {
 	}
 
 	/* send a newline so the server knows we're done with the request */
-	sprintf(send_buffer, "\r\n");
+	snprintf(send_buffer, MAX_INPUT_BUFFER, "\r\n");
 	sent_bytes = send(socket, send_buffer, strlen(send_buffer), 0);
 	if (sent_bytes == -1) {
 		mopl_utils_xasprintf(&sc_send.output, _("Sending newline to %s failed"), config.host_name);
@@ -221,8 +225,11 @@ int main(int argc, char **argv) {
 		mp_subcheck sc_describe = mp_subcheck_init();
 
 		/* send the DESCRIBE request */
-		sprintf(send_buffer, "DESCRIBE rtsp://%s:%d%s RTSP/1.0\r\n", config.host_name,
-				config.server_port, config.server_url);
+		int l = snprintf(send_buffer, MAX_INPUT_BUFFER, "DESCRIBE rtsp://%s:%d%s RTSP/1.0\r\n",
+						 config.host_name, config.server_port, config.server_url);
+		if (l >= MAX_INPUT_BUFFER) {
+			mopl_utils_usage4(_("Command arguments too long"));
+		}
 
 		ssize_t sent_bytes = send(socket, send_buffer, strlen(send_buffer), 0);
 		if (sent_bytes == -1) {
@@ -234,7 +241,7 @@ int main(int argc, char **argv) {
 		}
 
 		/* send the header sync */
-		sprintf(send_buffer, "CSeq: 2\r\n");
+		snprintf(send_buffer, MAX_INPUT_BUFFER, "CSeq: 2\r\n");
 		sent_bytes = send(socket, send_buffer, strlen(send_buffer), 0);
 		if (sent_bytes == -1) {
 			sc_describe = mp_set_subcheck_state(sc_describe, STATE_CRITICAL);
@@ -245,7 +252,7 @@ int main(int argc, char **argv) {
 		}
 
 		/* send a newline so the server knows we're done with the request */
-		sprintf(send_buffer, "\r\n");
+		snprintf(send_buffer, MAX_INPUT_BUFFER, "\r\n");
 		sent_bytes = send(socket, send_buffer, strlen(send_buffer), 0);
 		if (sent_bytes == -1) {
 			sc_describe = mp_set_subcheck_state(sc_describe, STATE_CRITICAL);



More information about the Commits mailing list