Descent3/scripts/linux_lib.cpp
Jan Engelhardt 97eeab914b Resolve out-of-bounds access in _splitpath
Crash at the start of every level.

==43628==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x5020000c5a6f at pc 0x7efd39f3868a bp 0x7ffe5a39ec80 sp 0x7ffe5a39ec78
READ of size 1 at 0x5020000c5a6f thread T0
    f0 _splitpath(char const*, char*, char*, char*, char*) $GIT/scripts/linux_lib.cpp:37
    f1 InitializeDLL $GIT/scripts/level1.cpp:705
    f2 Osiris_LoadLevelModule(char*) $GIT/Descent3/OsirisLoadandBind.cpp:1095
    f3 InitLevelScript() $GIT/Descent3/Mission.cpp:1699
    f4 StartLevel() $GIT/Descent3/gamesequence.cpp:1622
    f5 LoadAndStartCurrentLevel() $GIT/Descent3/gamesequence.cpp:1675
    f6 GameSequencer() $GIT/Descent3/gamesequence.cpp:1197
    f7 PlayGame() $GIT/Descent3/game.cpp:834
    f8 MainLoop() $GIT/Descent3/descent.cpp:555
    f9 Descent3() $GIT/Descent3/descent.cpp:508
    f10 oeD3LnxApp::run() $GIT/Descent3/sdlmain.cpp:151

0x5020000c5a6f is located 1 bytes before 7-byte region [0x5020000c5a70,0x5020000c5a77)
allocated by thread T0 here:
    f0 strdup (/lib64/libasan.so.8+0xf68e0) (BuildId: 5615a04b8d0a5a8eafa661f7235e2d98fa2b9137)
    f1 Osiris_LoadLevelModule(char*) $GIT/Descent3/OsirisLoadandBind.cpp:1046
    f2 InitLevelScript() $GIT/Descent3/Mission.cpp:1699
    f3 StartLevel() $GIT/Descent3/gamesequence.cpp:1622
    f4 LoadAndStartCurrentLevel() $GIT/Descent3/gamesequence.cpp:1675
    f5 GameSequencer() $GIT/Descent3/gamesequence.cpp:1197
    f6 PlayGame() $GIT/Descent3/game.cpp:834
    f7 MainLoop() $GIT/Descent3/descent.cpp:555
    f8 Descent3() $GIT/Descent3/descent.cpp:508
    f9 oeD3LnxApp::run() $GIT/Descent3/sdlmain.cpp:151
2024-08-31 12:13:44 +02:00

98 lines
2.6 KiB
C++

/*
* Descent 3
* Copyright (C) 2024 Parallax Software
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstring>
void _splitpath(const char *srcPath, char *drive, char *path, char *filename, char *ext) {
int pathStart = -1;
int pathEnd = -1;
int fileStart = -1;
int fileEnd = -1;
int extStart = -1;
int extEnd = -1;
int totalLen = strlen(srcPath);
if (drive)
*drive = '\0';
// Check for an extension
///////////////////////////////////////
int t = totalLen - 1;
while (t >= 0 && (srcPath[t] != '.') && (srcPath[t] != '/') && (t >= 0))
t--;
// see if we are at an extension
if ((t >= 0) && (srcPath[t] == '.')) {
// we have an extension
extStart = t;
extEnd = totalLen - 1;
if (ext) {
strncpy(ext, &(srcPath[extStart]), extEnd - extStart + 1);
ext[extEnd - extStart + 1] = '\0';
}
} else {
// no extension
if (ext)
ext[0] = '\0';
}
// Check for file name
////////////////////////////////////
int temp = (extStart != -1) ? (extStart) : (totalLen - 1);
while (temp >= 0 && (srcPath[temp] != '/') && (temp >= 0))
temp--;
if (temp < 0)
temp = 0;
if (srcPath[temp] == '/') {
// we have a file
fileStart = temp + 1;
if (extStart != -1)
fileEnd = extStart - 1;
else
fileEnd = totalLen - 1;
if (filename) {
strncpy(filename, &(srcPath[fileStart]), fileEnd - fileStart + 1);
filename[fileEnd - fileStart + 1] = '\0';
}
pathStart = 0;
pathEnd = fileStart - 2;
// Copy the rest into the path name
if (path) {
strncpy(path, &(srcPath[pathStart]), pathEnd - pathStart + 1);
path[pathEnd - pathStart + 1] = 0;
}
} else {
// only file, no path
fileStart = 0;
if (extStart != -1)
fileEnd = extStart - 1;
else
fileEnd = totalLen - 1;
if (filename) {
strncpy(filename, &(srcPath[fileStart]), fileEnd - fileStart + 1);
filename[fileEnd - fileStart + 1] = 0;
}
// Only file no path
if (path) {
path[0] = 0;
}
}
}