From 118305e4814c3f5034d0a291042dd7436afdc30c Mon Sep 17 00:00:00 2001 From: alexguirre Date: Sat, 12 Aug 2023 10:03:28 +0200 Subject: [PATCH] Fix crashes due to malicious RPFs RpfFile: - Limit RPF entry names to 256 characters because long names can cause the RPFExplorer to freeze when opening its directory. - Skip RPFs with paths longer that 5000 characters, which are probably an attempt to make CW run out-of-memory. ExploreForm: - Use `Path.GetExtension` directly instead of `FileInfo` to prevent `PathTooLongException`s. - Check for invalid characters in file names to prevent `ArgumentException`s. --- CodeWalker.Core/GameFiles/RpfFile.cs | 7 ++++++- CodeWalker/ExploreForm.cs | 9 +++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CodeWalker.Core/GameFiles/RpfFile.cs b/CodeWalker.Core/GameFiles/RpfFile.cs index ad4178a..53d8e78 100644 --- a/CodeWalker.Core/GameFiles/RpfFile.cs +++ b/CodeWalker.Core/GameFiles/RpfFile.cs @@ -215,6 +215,11 @@ namespace CodeWalker.GameFiles namesrdr.Position = e.NameOffset; e.Name = namesrdr.ReadString(); + if (e.Name.Length > 256) + { + // long names can freeze the RPFExplorer + e.Name = e.Name.Substring(0, 256); + } e.NameLower = e.Name.ToLowerInvariant(); if ((e is RpfFileEntry) && string.IsNullOrEmpty(e.Name)) @@ -312,7 +317,7 @@ namespace CodeWalker.GameFiles //search all the sub resources for YSC files. (recurse!) string lname = binentry.NameLower; - if (lname.EndsWith(".rpf")) + if (lname.EndsWith(".rpf") && binentry.Path.Length < 5000) // a long path is most likely an attempt to crash CW, so skip it { br.BaseStream.Position = StartPos + ((long)binentry.FileOffset * 512); diff --git a/CodeWalker/ExploreForm.cs b/CodeWalker/ExploreForm.cs index 2d8319f..bd25389 100644 --- a/CodeWalker/ExploreForm.cs +++ b/CodeWalker/ExploreForm.cs @@ -25,6 +25,7 @@ namespace CodeWalker private volatile bool Ready = false; private Dictionary FileTypes; + private readonly char[] InvalidFileNameChars = Path.GetInvalidFileNameChars(); private MainTreeFolder RootFolder; private List ExtraRootFolders = new List(); @@ -333,8 +334,12 @@ namespace CodeWalker } public FileTypeInfo GetFileType(string fn) { - var fi = new FileInfo(fn); - var ext = fi.Extension.ToLowerInvariant(); + if (fn.IndexOfAny(InvalidFileNameChars) != -1) + { + return FileTypes[""]; + } + + var ext = Path.GetExtension(fn).ToLowerInvariant(); if (!string.IsNullOrEmpty(ext)) { FileTypeInfo ft;