From 69dfbe06ce02e6199444245397acf79fb6857b4c Mon Sep 17 00:00:00 2001
From: Ralph Giles <giles@thaumas.net>
Date: Sun, 17 Sep 2023 11:49:12 -0700
Subject: [PATCH] oggenc: Don't assume the output path ends in a file name.

Origin: https://gitlab.xiph.org/xiph/vorbis-tools/-/merge_requests/7

oggenc attempts to create any specified directories in the output
file path if they don't exist. The parser was assuming there was
a final filename after the last directory separator, and so would
try to read off the end of the argument if it was a bare directory
such as `./` or `outdir/`. This adds a check to make sure the
scan isn't starting off the end of the path string.

Thanks to Frank-Z7 (Zeng Yunxiang) at Huazhong University of Science
and Technology (cse.hust.edu.cn) for the report.
---
 oggenc/platform.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/oggenc/platform.c b/oggenc/platform.c
index 6d9f4ef..ee0b7ce 100644
--- a/oggenc/platform.c
+++ b/oggenc/platform.c
@@ -136,18 +136,23 @@ int create_directories(char *fn, int isutf8)
 {
     char *end, *start;
     struct stat statbuf;
-    char *segment = malloc(strlen(fn)+1);
+    const size_t fn_len = strlen(fn);
+    char *segment = malloc(fn_len+1);
 #ifdef _WIN32
     wchar_t seg[MAX_PATH+1];
 #endif
 
     start = fn;
 #ifdef _WIN32
-    if(strlen(fn) >= 3 && isalpha(fn[0]) && fn[1]==':')
+    // Strip drive prefix
+    if(fn_len >= 3 && isalpha(fn[0]) && fn[1]==':') {
         start = start+2;
+    }
 #endif
 
-    while((end = strpbrk(start+1, PATH_SEPS)) != NULL)
+    // Loop through path segments, creating directories if necessary
+    while((start+1 - fn < fn_len) &&
+          (end = strpbrk(start+1, PATH_SEPS)) != NULL)
     {
         int rv;
         memcpy(segment, fn, end-fn);
@@ -159,7 +164,7 @@ int create_directories(char *fn, int isutf8)
             rv = _wstat(seg,&statbuf);
         } else
 #endif
-            rv = stat(segment,&statbuf);
+        rv = stat(segment, &statbuf);
         if(rv) {
             if(errno == ENOENT) {
 #ifdef _WIN32
-- 
GitLab

