aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCody Robibero <cody@robibe.ro>2026-08-30 17:52:39 -0400
committerGitHub <noreply@github.com>2026-08-30 17:52:39 -0400
commit7d6633ad1e9b4b69be87b2ac601fcadbacc37376 (patch)
tree6226761d735d99cd3114eb781177cd2435d0a9bf
parent420d44f638c44b942b43303c3165c2e8795b9020 (diff)
parent11adad0e67f9487536ed8e727955645c4dee4244 (diff)
Merge pull request #17744 from Shadowghost/fix-masterHEADmaster
Fix formatting and test
-rw-r--r--MediaBrowser.Controller/IO/FileSystemHelper.cs11
-rw-r--r--src/Jellyfin.Drawing.Skia/SvgSecurityValidator.cs58
-rw-r--r--tests/Jellyfin.Controller.Tests/IO/FileSystemHelperTests.cs20
3 files changed, 56 insertions, 33 deletions
diff --git a/MediaBrowser.Controller/IO/FileSystemHelper.cs b/MediaBrowser.Controller/IO/FileSystemHelper.cs
index f636258191..b2d2273cbe 100644
--- a/MediaBrowser.Controller/IO/FileSystemHelper.cs
+++ b/MediaBrowser.Controller/IO/FileSystemHelper.cs
@@ -193,8 +193,13 @@ public static class FileSystemHelper
var fullParentPath = Path.TrimEndingDirectorySeparator(Path.GetFullPath(parentPath));
// Catches the remaining relative names, "." and "..", which are valid single segments.
- return string.Equals(Path.GetDirectoryName(fullPath), fullParentPath, StringComparison.Ordinal)
- ? fullPath
- : null;
+ if (!string.Equals(Path.GetDirectoryName(fullPath), fullParentPath, StringComparison.Ordinal))
+ {
+ return null;
+ }
+
+ // Windows strips trailing dots and spaces, so a name like "..." resolves to the parent directory itself
+ // and a name like "Movies." to a different child. Reject anything normalization did not leave intact.
+ return string.Equals(Path.GetFileName(fullPath), name, StringComparison.Ordinal) ? fullPath : null;
}
}
diff --git a/src/Jellyfin.Drawing.Skia/SvgSecurityValidator.cs b/src/Jellyfin.Drawing.Skia/SvgSecurityValidator.cs
index f8a1d7d443..65f35643b2 100644
--- a/src/Jellyfin.Drawing.Skia/SvgSecurityValidator.cs
+++ b/src/Jellyfin.Drawing.Skia/SvgSecurityValidator.cs
@@ -83,48 +83,48 @@ internal static class SvgSecurityValidator
switch (reader.NodeType)
{
case XmlNodeType.DocumentType:
- {
- var subset = reader.Value;
- if (!string.IsNullOrEmpty(subset)
- && (subset.Contains("SYSTEM", StringComparison.OrdinalIgnoreCase)
- || subset.Contains("PUBLIC", StringComparison.OrdinalIgnoreCase)))
{
- return "The document declares an external DTD entity";
- }
+ var subset = reader.Value;
+ if (!string.IsNullOrEmpty(subset)
+ && (subset.Contains("SYSTEM", StringComparison.OrdinalIgnoreCase)
+ || subset.Contains("PUBLIC", StringComparison.OrdinalIgnoreCase)))
+ {
+ return "The document declares an external DTD entity";
+ }
- break;
- }
+ break;
+ }
case XmlNodeType.Element when reader.HasAttributes:
- {
- for (var i = 0; i < reader.AttributeCount; i++)
{
- reader.MoveToAttribute(i);
- var isHref = reader.LocalName.Equals("href", StringComparison.OrdinalIgnoreCase);
- var reason = isHref
- ? ValidateReference(reader.Value, depth, "href")
- : ValidateCss(reader.Value, depth);
- if (reason is not null)
+ for (var i = 0; i < reader.AttributeCount; i++)
{
- return reason;
+ reader.MoveToAttribute(i);
+ var isHref = reader.LocalName.Equals("href", StringComparison.OrdinalIgnoreCase);
+ var reason = isHref
+ ? ValidateReference(reader.Value, depth, "href")
+ : ValidateCss(reader.Value, depth);
+ if (reason is not null)
+ {
+ return reason;
+ }
}
- }
- reader.MoveToElement();
- break;
- }
+ reader.MoveToElement();
+ break;
+ }
case XmlNodeType.Text:
case XmlNodeType.CDATA:
- {
- var reason = ValidateCss(reader.Value, depth);
- if (reason is not null)
{
- return reason;
- }
+ var reason = ValidateCss(reader.Value, depth);
+ if (reason is not null)
+ {
+ return reason;
+ }
- break;
- }
+ break;
+ }
}
}
diff --git a/tests/Jellyfin.Controller.Tests/IO/FileSystemHelperTests.cs b/tests/Jellyfin.Controller.Tests/IO/FileSystemHelperTests.cs
index 4c7addd164..b4ec2f1903 100644
--- a/tests/Jellyfin.Controller.Tests/IO/FileSystemHelperTests.cs
+++ b/tests/Jellyfin.Controller.Tests/IO/FileSystemHelperTests.cs
@@ -13,7 +13,6 @@ public class FileSystemHelperTests
[InlineData("Movies")]
[InlineData("My Movies")]
[InlineData("..2")]
- [InlineData("...")]
[InlineData("a.b")]
public void GetChildPath_ValidName_ReturnsPathInsideParent(string name)
{
@@ -50,6 +49,25 @@ public class FileSystemHelperTests
Assert.True(path is null || string.Equals(Path.GetDirectoryName(path), _parentPath, StringComparison.Ordinal));
}
+ [Theory]
+ [InlineData("...")]
+ [InlineData("Movies.")]
+ [InlineData("Movies ")]
+ public void GetChildPath_TrailingDotOrSpace_RejectedOnWindows(string name)
+ {
+ var path = FileSystemHelper.GetChildPath(_parentPath, name);
+
+ if (OperatingSystem.IsWindows())
+ {
+ // Windows trims trailing dots and spaces, so the name would resolve to the parent or to a different child.
+ Assert.Null(path);
+ }
+ else
+ {
+ Assert.Equal(Path.Combine(_parentPath, name), path);
+ }
+ }
+
[Fact]
public void GetChildPath_ParentWithTrailingSeparator_ReturnsPathInsideParent()
{