[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