From c4049cb7a09d9a4f4d15d3734455c37bb8a49c08 Mon Sep 17 00:00:00 2001
From: chrfranke <chrfranke@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Wed, 8 May 2024 13:46:51 +0000
Subject: [PATCH] smartctl.cpp, smartd.cpp: Fix segfault on missing option
 argument (#1830).

getopt*() from musl libc sets 'optind = argc + 1' if the argument of
a short option is missing.

git-svn-id: https://svn.code.sf.net/p/smartmontools/code/trunk@5613 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 smartmontools/ChangeLog    | 7 +++++++
 smartmontools/smartctl.cpp | 3 ++-
 smartmontools/smartd.cpp   | 3 ++-
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/smartmontools/ChangeLog b/smartmontools/ChangeLog
index 296ef7be5..eebc8cae3 100644
--- a/smartmontools/ChangeLog
+++ b/smartmontools/ChangeLog
@@ -1,5 +1,12 @@
 $Id$
 
+2024-05-08  Christian Franke  <franke@computer.org>
+
+	smartctl.cpp, smartd.cpp: Fix segfault on missing option argument (#1830).
+
+	getopt*() from musl libc sets 'optind = argc + 1' if the argument of
+	a short option is missing.
+
 2024-04-26  Christian Franke  <franke@computer.org>
 
 	os_win32/vc1[67]/*: Set svn:eol-style=CRLF, MSVC does not preserve LF.
diff --git a/smartmontools/smartctl.cpp b/smartmontools/smartctl.cpp
index 15f22a7b7..67d1beef2 100644
--- a/smartmontools/smartctl.cpp
+++ b/smartmontools/smartctl.cpp
@@ -1168,7 +1168,8 @@ static int parse_options(int argc, char** argv, const char * & type,
       printing_is_off = false;
       printslogan();
       // Point arg to the argument in which this option was found.
-      arg = argv[optind-1];
+      // Note: getopt_long() may set optind > argc (e.g. musl libc)
+      arg = argv[optind <= argc ? optind - 1 : argc - 1];
       // Check whether the option is a long option that doesn't map to -h.
       if (arg[1] == '-' && optchar != 'h') {
         // Iff optopt holds a valid option then argument must be missing.
diff --git a/smartmontools/smartd.cpp b/smartmontools/smartd.cpp
index b6473c8ea..34f2cde23 100644
--- a/smartmontools/smartd.cpp
+++ b/smartmontools/smartd.cpp
@@ -5361,7 +5361,8 @@ static int parse_options(int argc, char **argv)
       debugmode=1;
       PrintHead();
       // Point arg to the argument in which this option was found.
-      arg = argv[optind-1];
+      // Note: getopt_long() may set optind > argc (e.g. musl libc)
+      arg = argv[optind <= argc ? optind - 1 : argc - 1];
       // Check whether the option is a long option that doesn't map to -h.
       if (arg[1] == '-' && optchar != 'h') {
         // Iff optopt holds a valid option then argument must be missing.
-- 
GitLab