Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions src/SMAPI/Framework/ContentManagers/ModContentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,19 @@ private void FixTilesheetPaths(Map map, string relativeMapPath, bool fixEagerPat

// validate tilesheet path
string errorPrefix = $"{this.ModName} loaded map '{relativeMapPath}' with invalid tilesheet path '{imageSource}'.";
if (Path.IsPathRooted(imageSource) || PathUtilities.GetSegments(imageSource).Contains(".."))
throw new SContentLoadException(ContentLoadErrorType.InvalidData, $"{errorPrefix} Tilesheet paths must be a relative path without directory climbing (../).");
if (Path.IsPathRooted(imageSource))
throw new SContentLoadException(ContentLoadErrorType.InvalidData, $"{errorPrefix} Tilesheet paths must not be an absolute path ({Path.GetPathRoot(imageSource)}).");

string[] imageSourcePathSegments = PathUtilities.GetSegments(imageSource);
if (imageSourcePathSegments.Contains(".."))
{
int climbingCount = imageSourcePathSegments.Count(segment => segment.Equals("..", StringComparison.OrdinalIgnoreCase));
if (climbingCount > 1)
{
string[] offendingSegments = imageSourcePathSegments.TakeWhile(seg => seg.Equals("..")).ToArray();
throw new SContentLoadException(ContentLoadErrorType.InvalidData, $"{errorPrefix} Tilesheet paths must not climb more than one directory ({string.Join('/', offendingSegments)}/).");
}
}

// load best match
try
Expand Down Expand Up @@ -467,8 +478,8 @@ private bool TryGetTilesheetAssetName(string modRelativeMapFolder, string relati
relativePath = Path.Combine(Path.GetDirectoryName(relativePath) ?? "", filename.TrimStart('.'));
}

// get relative to map file
{
// get relative to map file unless path has directory climbing
if (!PathUtilities.GetSegments(relativePath).Contains("..")) {
string localKey = Path.Combine(modRelativeMapFolder, relativePath);
if (this.GetModFile<Texture2D>(localKey).Exists)
{
Expand Down Expand Up @@ -524,8 +535,12 @@ private string GetContentKeyForTilesheetImageSource(string relativePath)
string key = relativePath;
string topFolder = PathUtilities.GetSegments(key, limit: 2)[0];

// convert image source relative to map file into asset key
if (!topFolder.Equals("Maps", StringComparison.OrdinalIgnoreCase))
// remove previously validated directory climbing if it exists
if (topFolder.Equals("..", StringComparison.OrdinalIgnoreCase))
key = key[2..];

// else convert image source relative to map file into asset key
else if (!topFolder.Equals("Maps", StringComparison.OrdinalIgnoreCase))
key = Path.Combine("Maps", key);

// remove file extension from unpacked file
Expand Down