fallout2-ce icon indicating copy to clipboard operation
fallout2-ce copied to clipboard

Fix Nevada-Foxx crash on Linux/Webassembly platform

Open roginvs opened this issue 2 years ago • 0 comments

In current implementation we assume that compat_splitpath will receive files with / when we are running on Linux platform. This is mostly true except cases when path is originated from ddraw.ini. Here is example from "Nevada build by Foxx":

[Scripts]
GlobalScriptPaths=scripts\gl*.int,mods\sFall\gl*.int

NOTE: One should run this on case-insensitive file system or rename folders according to configuration. No folder - no bug and no global scripts of course.

So, in this PR we use another compat_splitpath implementation which works on both / and \

Here are unit tests for this, it will be good to include them directly into codebase and setup CI check (do you have any ideas how to make it?)
#include <stdio.h>
#include <string.h>


#define COMPAT_MAX_DRIVE 3
#define COMPAT_MAX_DIR 256
#define COMPAT_MAX_FNAME 256
#define COMPAT_MAX_EXT 256


void compat_splitpath(const char* path, char* drive, char* dir, char* fname, char* ext);

// A macro to compare the expected and actual values
#define ASSERT_EQUAL_STR(expected, actual)                              \
    if (strcmp(expected, actual) != 0) {                                \
        printf("FAILURE: Expected '%s', got '%s'\n", expected, actual); \
        return 0;                                                       \
    }

int test1()
{
    char drive[COMPAT_MAX_DRIVE];
    char dir[COMPAT_MAX_DIR];
    char fname[COMPAT_MAX_FNAME];
    char ext[COMPAT_MAX_EXT];

    compat_splitpath("/path/to/file.txt", drive, dir, fname, ext);

    ASSERT_EQUAL_STR("", drive);
    ASSERT_EQUAL_STR("/path/to/", dir);
    ASSERT_EQUAL_STR("file", fname);
    ASSERT_EQUAL_STR(".txt", ext);
    printf("Test1 PASSED\n");
    return 1;
}

int test2()
{
    char drive[COMPAT_MAX_DRIVE];
    char dir[COMPAT_MAX_DIR];
    char fname[COMPAT_MAX_FNAME];
    char ext[COMPAT_MAX_EXT];

    compat_splitpath("C:\\path\\to\\file.txt", drive, dir, fname, ext);

    ASSERT_EQUAL_STR("C:", drive);
    ASSERT_EQUAL_STR("\\path\\to\\", dir);
    ASSERT_EQUAL_STR("file", fname);
    ASSERT_EQUAL_STR(".txt", ext);
    printf("Test2 PASSED\n");
    return 1;
}

int test3()
{
    char drive[COMPAT_MAX_DRIVE];
    char dir[COMPAT_MAX_DIR];
    char fname[COMPAT_MAX_FNAME];
    char ext[COMPAT_MAX_EXT];

    compat_splitpath("file.txt", drive, dir, fname, ext);

    ASSERT_EQUAL_STR("", drive);
    ASSERT_EQUAL_STR("", dir);
    ASSERT_EQUAL_STR("file", fname);
    ASSERT_EQUAL_STR(".txt", ext);
    printf("Test3 PASSED\n");
    return 1;
}

int test_no_disk()
{
    char drive[COMPAT_MAX_DRIVE];
    char dir[COMPAT_MAX_DIR];
    char fname[COMPAT_MAX_FNAME];
    char ext[COMPAT_MAX_EXT];

    compat_splitpath("\\path\\without\\disk\\file.txt", drive, dir, fname, ext);

    ASSERT_EQUAL_STR("", drive);
    ASSERT_EQUAL_STR("\\path\\without\\disk\\", dir);
    ASSERT_EQUAL_STR("file", fname);
    ASSERT_EQUAL_STR(".txt", ext);
    printf("Test_no_disk PASSED\n");
    return 1;
}

int test_no_leading_backslash()
{
    char drive[COMPAT_MAX_DRIVE];
    char dir[COMPAT_MAX_DIR];
    char fname[COMPAT_MAX_FNAME];
    char ext[COMPAT_MAX_EXT];

    compat_splitpath("path\\without\\leading\\file.txt", drive, dir, fname, ext);

    ASSERT_EQUAL_STR("", drive);
    ASSERT_EQUAL_STR("path\\without\\leading\\", dir);
    ASSERT_EQUAL_STR("file", fname);
    ASSERT_EQUAL_STR(".txt", ext);
    printf("Test_no_leading_backslash PASSED\n");
    return 1;
}

int test_dot_in_filename()
{
    char drive[COMPAT_MAX_DRIVE];
    char dir[COMPAT_MAX_DIR];
    char fname[COMPAT_MAX_FNAME];
    char ext[COMPAT_MAX_EXT];

    compat_splitpath("/path/with/dotted.file.txt", drive, dir, fname, ext);

    ASSERT_EQUAL_STR("", drive);
    ASSERT_EQUAL_STR("/path/with/", dir);
    ASSERT_EQUAL_STR("dotted.file", fname);
    ASSERT_EQUAL_STR(".txt", ext);
    printf("Test_dot_in_filename PASSED\n");
    return 1;
}

int test_no_extension()
{
    char drive[COMPAT_MAX_DRIVE];
    char dir[COMPAT_MAX_DIR];
    char fname[COMPAT_MAX_FNAME];
    char ext[COMPAT_MAX_EXT];

    compat_splitpath("/path/with/noextensionfile", drive, dir, fname, ext);

    ASSERT_EQUAL_STR("", drive);
    ASSERT_EQUAL_STR("/path/with/", dir);
    ASSERT_EQUAL_STR("noextensionfile", fname);
    ASSERT_EQUAL_STR("", ext);
    printf("Test_no_extension PASSED\n");
    return 1;
}

int main()
{
    if (!test1()) return 1;
    if (!test2()) return 1;
    if (!test3()) return 1;
    if (!test_no_disk()) return 1;
    if (!test_no_leading_backslash()) return 1;
    if (!test_dot_in_filename()) return 1;
    if (!test_no_extension()) return 1;

    printf("All tests passed.\n");
    return 0;
}

roginvs avatar Oct 09 '23 17:10 roginvs