diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a87f54041..eb7d4cc404 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Apply the propagation context to events that already have contexts set, so that events captured with a local scope or with event-level contexts keep their trace. ([#1843](https://github.com/getsentry/sentry-native/pull/1843)) - Route libcurl debug output through the Sentry logger (`SENTRY_TRACE`) instead of writing to `stderr`. ([#1854](https://github.com/getsentry/sentry-native/pull/1854)) - NOTE: `sentry_options_set_debug(options, true)` no longer displays verbose libcurl debug output by default. To restore it, call `sentry_options_set_logger_level(options, SENTRY_LEVEL_TRACE)`. +- Windows: fix symlink detection used to prevent database cleanup from following symlinks in run and cache directories. ([#1857](https://github.com/getsentry/sentry-native/pull/1857)) ## 0.15.3 diff --git a/src/path/sentry_path_windows.c b/src/path/sentry_path_windows.c index b27b4d2486..7169a89afd 100644 --- a/src/path/sentry_path_windows.c +++ b/src/path/sentry_path_windows.c @@ -359,8 +359,21 @@ sentry__path_is_symlink(const sentry_path_t *path) return false; } const DWORD attributes = GetFileAttributesW(path_w); - return attributes != INVALID_FILE_ATTRIBUTES - && (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0; + if (attributes == INVALID_FILE_ATTRIBUTES + || (attributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) { + return false; + } + + // https://learn.microsoft.com/en-us/windows/win32/fileio/reparse-point-tags + WIN32_FIND_DATAW data; + const HANDLE find_handle = FindFirstFileW(path_w, &data); + if (find_handle == INVALID_HANDLE_VALUE) { + return true; + } + FindClose(find_handle); + + return (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0 + && IsReparseTagNameSurrogate(data.dwReserved0) != 0; } size_t diff --git a/src/sentry_path.h b/src/sentry_path.h index 4275c01754..afe8247905 100644 --- a/src/sentry_path.h +++ b/src/sentry_path.h @@ -149,7 +149,8 @@ bool sentry__path_ends_with(const sentry_path_t *path, const char *suffix); bool sentry__path_is_dir(const sentry_path_t *path); /** - * Return whether the path refers to a symlink. + * Return whether the path refers to a symlink. On Windows, this includes + * name-surrogate reparse points such as junctions. */ bool sentry__path_is_symlink(const sentry_path_t *path); diff --git a/tests/unit/test_path.c b/tests/unit/test_path.c index 6b782e8285..7ebe2045a9 100644 --- a/tests/unit/test_path.c +++ b/tests/unit/test_path.c @@ -2,7 +2,27 @@ #include "sentry_string.h" #include "sentry_testsupport.h" -#if defined(SENTRY_PLATFORM_UNIX) && !defined(SENTRY_PLATFORM_NX) \ +#if defined(SENTRY_PLATFORM_WINDOWS) && !defined(SENTRY_PLATFORM_XBOX) +static int +symlink(const char *target, const char *link) +{ + sentry_path_t *target_path = sentry__path_from_str(target); + sentry_path_t *link_path = sentry__path_from_str(link); + if (!target_path || !link_path) { + sentry__path_free(link_path); + sentry__path_free(target_path); + return -1; + } + + BOOLEAN success + = CreateSymbolicLinkW(link_path->path_w, target_path->path_w, + SYMBOLIC_LINK_FLAG_DIRECTORY + | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE); + sentry__path_free(link_path); + sentry__path_free(target_path); + return success ? 0 : -1; +} +#elif defined(SENTRY_PLATFORM_UNIX) && !defined(SENTRY_PLATFORM_NX) \ && !defined(SENTRY_PLATFORM_PS) # include #endif @@ -254,8 +274,8 @@ SENTRY_TEST(path_directory) SENTRY_TEST(path_remove_all_symlink) { -#if !defined(SENTRY_PLATFORM_UNIX) || defined(SENTRY_PLATFORM_NX) \ - || defined(SENTRY_PLATFORM_PS) +#if defined(SENTRY_PLATFORM_NX) || defined(SENTRY_PLATFORM_PS) \ + || defined(SENTRY_PLATFORM_XBOX) SKIP_TEST(); #else sentry_path_t *base