From 665f8d2e3e52c3260bfc682044843a4183ecc210 Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@sudo.ws>
Date: Wed, 3 Feb 2021 16:50:04 -0700
Subject: [PATCH] Only strip double quotes from an include path if len >= 2.
 Found locally using libfuzzer/oss-fuzz.

---
 plugins/sudoers/toke.c | 13 ++++++++-----
 plugins/sudoers/toke.l | 13 ++++++++-----
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/plugins/sudoers/toke.c b/plugins/sudoers/toke.c
index 6717e4f..f8dd1e1 100644
--- a/plugins/sudoers/toke.c
+++ b/plugins/sudoers/toke.c
@@ -5201,26 +5201,29 @@ init_lexer(void)
  * Returns a reference-counted string.
  */
 static char *
-expand_include(const char *opath, size_t olen)
+expand_include(const char *opath)
 {
     const char *cp, *ep;
     char *path, *pp;
-    int dirlen = 0, len;
+    size_t len, olen, dirlen = 0;
     size_t shost_len = 0;
     bool subst = false;
     debug_decl(expand_include, SUDOERS_DEBUG_PARSER);
 
     /* Strip double quotes if present. */
-    if (*opath == '"') {
+    olen = strlen(opath);
+    if (olen > 1 && opath[0] == '"' && opath[olen - 1] == '"') {
 	opath++;
 	olen -= 2;
     }
+    if (olen == 0)
+	debug_return_ptr(NULL);
 
     /* Relative paths are located in the same dir as the sudoers file. */
     if (*opath != '/') {
 	char *dirend = strrchr(sudoers, '/');
 	if (dirend != NULL)
-	    dirlen = (int)(dirend - sudoers) + 1;
+	    dirlen = (size_t)(dirend - sudoers) + 1;
     }
 
     len = olen;
@@ -5278,7 +5281,7 @@ push_include(const char *opath, bool isdir)
     FILE *fp;
     debug_decl(push_include, SUDOERS_DEBUG_PARSER);
 
-    if ((path = expand_include(opath, strlen(opath))) == NULL)
+    if ((path = expand_include(opath)) == NULL)
 	debug_return_bool(false);
 
     /* push current state onto stack */
diff --git a/plugins/sudoers/toke.l b/plugins/sudoers/toke.l
index 499f3b1..22430ac 100644
--- a/plugins/sudoers/toke.l
+++ b/plugins/sudoers/toke.l
@@ -1006,26 +1006,29 @@ init_lexer(void)
  * Returns a reference-counted string.
  */
 static char *
-expand_include(const char *opath, size_t olen)
+expand_include(const char *opath)
 {
     const char *cp, *ep;
     char *path, *pp;
-    int dirlen = 0, len;
+    size_t len, olen, dirlen = 0;
     size_t shost_len = 0;
     bool subst = false;
     debug_decl(expand_include, SUDOERS_DEBUG_PARSER);
 
     /* Strip double quotes if present. */
-    if (*opath == '"') {
+    olen = strlen(opath);
+    if (olen > 1 && opath[0] == '"' && opath[olen - 1] == '"') {
 	opath++;
 	olen -= 2;
     }
+    if (olen == 0)
+	debug_return_ptr(NULL);
 
     /* Relative paths are located in the same dir as the sudoers file. */
     if (*opath != '/') {
 	char *dirend = strrchr(sudoers, '/');
 	if (dirend != NULL)
-	    dirlen = (int)(dirend - sudoers) + 1;
+	    dirlen = (size_t)(dirend - sudoers) + 1;
     }
 
     len = olen;
@@ -1083,7 +1086,7 @@ push_include(const char *opath, bool isdir)
     FILE *fp;
     debug_decl(push_include, SUDOERS_DEBUG_PARSER);
 
-    if ((path = expand_include(opath, strlen(opath))) == NULL)
+    if ((path = expand_include(opath)) == NULL)
 	debug_return_bool(false);
 
     /* push current state onto stack */
-- 
1.8.3.1

