From 0bb3446a8b0865d0eee41a0b2a7b382b5c01953a Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Mon, 23 Mar 2020 15:54:11 -0700 Subject: [PATCH 1/2] Make path parser check for a null terminator --- src/LibHac/FsSystem/PathParser.cs | 6 ++--- src/LibHac/FsSystem/Save/SaveFsList.cs | 3 ++- src/LibHac/Util.cs | 36 -------------------------- 3 files changed, 5 insertions(+), 40 deletions(-) diff --git a/src/LibHac/FsSystem/PathParser.cs b/src/LibHac/FsSystem/PathParser.cs index e6c3f51e..3182b1af 100644 --- a/src/LibHac/FsSystem/PathParser.cs +++ b/src/LibHac/FsSystem/PathParser.cs @@ -27,7 +27,7 @@ namespace LibHac.FsSystem _path = path; _offset = 0; _length = 0; - _finished = path.Length == 1; + _finished = path.Length == 1 || path[1] == '\0'; } /// @@ -57,12 +57,12 @@ namespace LibHac.FsSystem _offset = _offset + _length + 1; int end = _offset; - while (end < _path.Length && _path[end] != '/') + while (end < _path.Length && _path[end] != '\0' && _path[end] != '/') { end++; } - _finished = end + 1 >= _path.Length; + _finished = end + 1 >= _path.Length || _path[end + 1] == '\0'; _length = end - _offset; return true; diff --git a/src/LibHac/FsSystem/Save/SaveFsList.cs b/src/LibHac/FsSystem/Save/SaveFsList.cs index 2d83c572..add73f18 100644 --- a/src/LibHac/FsSystem/Save/SaveFsList.cs +++ b/src/LibHac/FsSystem/Save/SaveFsList.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using LibHac.Common; using LibHac.Fs; namespace LibHac.FsSystem.Save @@ -44,7 +45,7 @@ namespace LibHac.FsSystem.Save ReadEntry(index, out entry); - if (entry.Parent == key.Parent && Util.StringSpansEqual(name, key.Name)) + if (entry.Parent == key.Parent && StringUtils.Compare(name, key.Name) == 0) { return (index, prevIndex); } diff --git a/src/LibHac/Util.cs b/src/LibHac/Util.cs index cd41f537..7c226b5e 100644 --- a/src/LibHac/Util.cs +++ b/src/LibHac/Util.cs @@ -64,42 +64,6 @@ namespace LibHac return true; } - /// - /// Compares two strings stored int byte spans. For the strings to be equal, - /// they must terminate in the same place. - /// A string can be terminated by either a null character or the end of the span. - /// - /// The first string to be compared. - /// The first string to be compared. - /// if the strings are equal; - /// otherwise . - public static bool StringSpansEqual(ReadOnlySpan s1, ReadOnlySpan s2) - { - // Make s1 the long string for simplicity - if (s1.Length < s2.Length) - { - ReadOnlySpan tmp = s1; - s1 = s2; - s2 = tmp; - } - - int shortLength = s2.Length; - int i; - - for (i = 0; i < shortLength; i++) - { - if (s1[i] != s2[i]) return false; - - // Both strings are null-terminated - if (s1[i] == 0) return true; - } - - // The bytes in the short string equal those in the long. - // Check if the strings are the same length or if the next - // character in the long string is a null character - return s1.Length == s2.Length || s1[i] == 0; - } - public static ReadOnlySpan GetUtf8Bytes(string value) { return Encoding.UTF8.GetBytes(value).AsSpan(); From b8b2c264574ce56e82aa7991445ddb0079c21d2f Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Mon, 23 Mar 2020 16:04:49 -0700 Subject: [PATCH 2/2] Tweak duplicate result detection --- build/CodeGen/ResultCodegen.cs | 6 ++---- build/CodeGen/results.csv | 5 +++-- src/LibHac/Fs/ResultFs.cs | 6 +++--- src/LibHac/ResultNameResolver.cs | 7 ++++++- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/build/CodeGen/ResultCodegen.cs b/build/CodeGen/ResultCodegen.cs index 6a4ffc51..e147d04e 100644 --- a/build/CodeGen/ResultCodegen.cs +++ b/build/CodeGen/ResultCodegen.cs @@ -124,13 +124,11 @@ namespace LibHacBuild.CodeGen { foreach (ModuleInfo module in modules) { - var set = new HashSet(); + var set = new HashSet(); foreach (ResultInfo result in module.Results) { - long description = (long)result.DescriptionStart << 32 | (uint)result.DescriptionEnd; - - if (!set.Add(description)) + if (!set.Add(result.DescriptionStart)) { throw new InvalidDataException($"Duplicate result {result.Module}-{result.DescriptionStart}-{result.DescriptionEnd}."); } diff --git a/build/CodeGen/results.csv b/build/CodeGen/results.csv index 6e78b285..64ad0bfb 100644 --- a/build/CodeGen/results.csv +++ b/build/CodeGen/results.csv @@ -124,11 +124,12 @@ Module,DescriptionStart,DescriptionEnd,Name,Summary 2,4748,,AesXtsFileHeaderInvalidKeysInSetSize, 2,4761,4769,SaveDataTransferDataCorrupted, + 2,4771,4779,SignedSystemPartitionDataCorrupted, 2,4781,,GameCardLogoDataCorrupted, -2,4791,4799,MultiCommitContextCorrupted, -2,4791,,InvalidMultiCommitContextVersion,The version of the multi-commit context file is to high for the current MultiCommitManager implementation. +2,4790,4799,MultiCommitContextCorrupted, +2,4791,,InvalidMultiCommitContextVersion,The version of the multi-commit context file is too high for the current MultiCommitManager implementation. 2,4792,,InvalidMultiCommitContextState,The multi-commit has not been provisionally committed. # The range name is a guess. 4812 is currently the only result in it diff --git a/src/LibHac/Fs/ResultFs.cs b/src/LibHac/Fs/ResultFs.cs index 7725caf3..1da7e893 100644 --- a/src/LibHac/Fs/ResultFs.cs +++ b/src/LibHac/Fs/ResultFs.cs @@ -256,9 +256,9 @@ namespace LibHac.Fs /// Error code: 2002-4781; Inner value: 0x255a02 public static Result.Base GameCardLogoDataCorrupted => new Result.Base(ModuleFs, 4781); - /// Error code: 2002-4791; Range: 4791-4799; Inner value: 0x256e02 - public static Result.Base MultiCommitContextCorrupted { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 4791, 4799); } - /// The version of the multi-commit context file is to high for the current MultiCommitManager implementation.
Error code: 2002-4791; Inner value: 0x256e02
+ /// Error code: 2002-4790; Range: 4790-4799; Inner value: 0x256c02 + public static Result.Base MultiCommitContextCorrupted { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 4790, 4799); } + /// The version of the multi-commit context file is too high for the current MultiCommitManager implementation.
Error code: 2002-4791; Inner value: 0x256e02
public static Result.Base InvalidMultiCommitContextVersion => new Result.Base(ModuleFs, 4791); /// The multi-commit has not been provisionally committed.
Error code: 2002-4792; Inner value: 0x257002
public static Result.Base InvalidMultiCommitContextState => new Result.Base(ModuleFs, 4792); diff --git a/src/LibHac/ResultNameResolver.cs b/src/LibHac/ResultNameResolver.cs index 8cf1b9f8..2a685223 100644 --- a/src/LibHac/ResultNameResolver.cs +++ b/src/LibHac/ResultNameResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using LibHac.Common; @@ -47,7 +48,11 @@ namespace LibHac foreach (ref readonly Element element in elements) { var result = new Result(element.Module, element.DescriptionStart); - dict.Add(result, GetName(element.NameOffset).ToString()); + + if (!dict.TryAdd(result, GetName(element.NameOffset).ToString())) + { + throw new InvalidDataException("Invalid result name archive: Duplicate result found."); + } } return dict;