Add some validation to StorageBase

This commit is contained in:
Alex Barney 2019-10-11 12:53:29 -05:00
parent 54950c9b68
commit bfc343e801
9 changed files with 89 additions and 40 deletions

View file

@ -55,7 +55,7 @@ namespace LibHac.Fs
public Result GetSize(out long size)
{
size = 0;
size = default;
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
return GetSizeImpl(out size);

View file

@ -21,7 +21,7 @@ namespace LibHac.Fs
FsClient = Handle.File.Parent.FsClient;
}
public override Result Read(long offset, Span<byte> destination)
public override Result ReadImpl(long offset, Span<byte> destination)
{
lock (_locker)
{
@ -30,14 +30,13 @@ namespace LibHac.Fs
Result rc = UpdateSize();
if (rc.IsFailure()) return rc;
if (destination.Length < 0 || offset < 0) return ResultFs.ValueOutOfRange.Log();
if (!IsRangeValid(offset, destination.Length, FileSize)) return ResultFs.ValueOutOfRange.Log();
return FsClient.ReadFile(Handle, offset, destination);
}
}
public override Result Write(long offset, ReadOnlySpan<byte> source)
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
{
lock (_locker)
{
@ -46,26 +45,25 @@ namespace LibHac.Fs
Result rc = UpdateSize();
if (rc.IsFailure()) return rc;
if (source.Length < 0 || offset < 0) return ResultFs.ValueOutOfRange.Log();
if (!IsRangeValid(offset, source.Length, FileSize)) return ResultFs.ValueOutOfRange.Log();
return FsClient.WriteFile(Handle, offset, source);
}
}
public override Result Flush()
public override Result FlushImpl()
{
return FsClient.FlushFile(Handle);
}
public override Result SetSize(long size)
public override Result SetSizeImpl(long size)
{
FileSize = InvalidSize;
return FsClient.SetFileSize(Handle, size);
}
public override Result GetSize(out long size)
public override Result GetSizeImpl(out long size)
{
size = default;
@ -87,7 +85,7 @@ namespace LibHac.Fs
return Result.Success;
}
public override void Dispose()
protected override void Dispose(bool disposing)
{
if (CloseHandle)
{

View file

@ -205,8 +205,8 @@ namespace LibHac.Fs
{
None = 0,
Application = 1 << 0,
Internal = 1 << 1,
All = Application | Internal
System = 1 << 1,
All = Application | System
}
[Flags]

View file

@ -135,7 +135,7 @@
public static Result RemapStorageMapFull => new Result(ModuleFs, 6811);
public static Result Result6902 => new Result(ModuleFs, 6902);
public static Result SubStorageNotInitialized => new Result(ModuleFs, 6902);
public static Result MountNameNotFound => new Result(ModuleFs, 6905);
}
}

View file

@ -31,7 +31,7 @@ namespace LibHac.Fs
public static Result CreateSystemSaveData(this FileSystemClient fs, SaveDataSpaceId spaceId,
ulong saveDataId, UserId userId, ulong ownerId, long size, long journalSize, uint flags)
{
return fs.RunOperationWithAccessLog(LocalAccessLogMode.Internal,
return fs.RunOperationWithAccessLog(LocalAccessLogMode.System,
() =>
{
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();
@ -89,7 +89,7 @@ namespace LibHac.Fs
public static Result DeleteSaveData(this FileSystemClient fs, ulong saveDataId)
{
return fs.RunOperationWithAccessLog(LocalAccessLogMode.Internal,
return fs.RunOperationWithAccessLog(LocalAccessLogMode.System,
() =>
{
IFileSystemProxy fsProxy = fs.GetFileSystemProxyServiceObject();

View file

@ -1,20 +1,71 @@
using System;
using System.Threading;
namespace LibHac.Fs
{
public abstract class StorageBase : IStorage
{
public abstract Result Read(long offset, Span<byte> destination);
public abstract Result Write(long offset, ReadOnlySpan<byte> source);
public abstract Result Flush();
public abstract Result SetSize(long size);
public abstract Result GetSize(out long size);
// 0 = not disposed; 1 = disposed
private int _disposedState;
private bool IsDisposed => _disposedState != 0;
public virtual void Dispose() { }
public abstract Result ReadImpl(long offset, Span<byte> destination);
public abstract Result WriteImpl(long offset, ReadOnlySpan<byte> source);
public abstract Result FlushImpl();
public abstract Result GetSizeImpl(out long size);
public abstract Result SetSizeImpl(long size);
public Result Read(long offset, Span<byte> destination)
{
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
return ReadImpl(offset, destination);
}
public Result Write(long offset, ReadOnlySpan<byte> source)
{
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
return WriteImpl(offset, source);
}
public Result Flush()
{
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
return FlushImpl();
}
public Result SetSize(long size)
{
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
return SetSizeImpl(size);
}
public Result GetSize(out long size)
{
size = default;
if (IsDisposed) return ResultFs.PreconditionViolation.Log();
return GetSizeImpl(out size);
}
public void Dispose()
{
// Make sure Dispose is only called once
if (Interlocked.CompareExchange(ref _disposedState, 1, 0) == 0)
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
protected virtual void Dispose(bool disposing) { }
public static bool IsRangeValid(long offset, long size, long totalSize)
{
return size <= totalSize && offset <= totalSize - size;
return offset >= 0 && size >= 0 && size <= totalSize && offset <= totalSize - size;
}
}
}

View file

@ -23,38 +23,38 @@ namespace LibHac.Fs
Size = size;
}
public override Result Read(long offset, Span<byte> destination)
public override Result ReadImpl(long offset, Span<byte> destination)
{
if (BaseStorage == null) return ResultFs.Result6902.Log();
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
if (destination.Length == 0) return Result.Success;
if (Size < 0 || offset < 0) return ResultFs.ValueOutOfRange.Log();
if (!IsRangeValid(offset, destination.Length, Size)) return ResultFs.ValueOutOfRange.Log();
return BaseStorage.Read(Offset + offset, destination);
}
public override Result Write(long offset, ReadOnlySpan<byte> source)
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
{
if (BaseStorage == null) return ResultFs.Result6902.Log();
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
if (source.Length == 0) return Result.Success;
if (Size < 0 || offset < 0) return ResultFs.ValueOutOfRange.Log();
if (!IsRangeValid(offset, source.Length, Size)) return ResultFs.ValueOutOfRange.Log();
return BaseStorage.Write(Offset + offset, source);
}
public override Result Flush()
public override Result FlushImpl()
{
if (BaseStorage == null) return ResultFs.Result6902.Log();
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
return BaseStorage.Flush();
}
public override Result SetSize(long size)
public override Result SetSizeImpl(long size)
{
if (BaseStorage == null) return ResultFs.Result6902.Log();
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
if (!IsResizable) return ResultFs.SubStorageNotResizable.Log();
if (size < 0 || Offset < 0) return ResultFs.ValueOutOfRange.Log();
if (size < 0 || Offset < 0) return ResultFs.InvalidSize.Log();
Result rc = BaseStorage.GetSize(out long baseSize);
if (rc.IsFailure()) return rc;
@ -72,11 +72,11 @@ namespace LibHac.Fs
return Result.Success;
}
public override Result GetSize(out long size)
public override Result GetSizeImpl(out long size)
{
size = default;
if (BaseStorage == null) return ResultFs.Result6902.Log();
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
size = Size;
return Result.Success;

View file

@ -87,7 +87,7 @@ namespace LibHac.FsService.Creators
imageHash.CopyTo(ImageHash);
}
public override Result Read(long offset, Span<byte> destination)
public override Result ReadImpl(long offset, Span<byte> destination)
{
// In secure mode, if Handle is old and the card's device ID and
// header hash are still the same, Handle is updated to the new handle
@ -95,22 +95,22 @@ namespace LibHac.FsService.Creators
return GameCard.Read(Handle, offset, destination);
}
public override Result Write(long offset, ReadOnlySpan<byte> source)
public override Result WriteImpl(long offset, ReadOnlySpan<byte> source)
{
return ResultFs.UnsupportedOperationInRoGameCardStorageWrite.Log();
}
public override Result Flush()
public override Result FlushImpl()
{
return Result.Success;
}
public override Result SetSize(long size)
public override Result SetSizeImpl(long size)
{
return ResultFs.UnsupportedOperationInRoGameCardStorageSetSize.Log();
}
public override Result GetSize(out long size)
public override Result GetSizeImpl(out long size)
{
size = 0;

View file

@ -62,7 +62,7 @@ namespace LibHac.FsSystem
public override Result SetSize(long size)
{
if (BaseStorage == null) return ResultFs.Result6902.Log();
if (BaseStorage == null) return ResultFs.SubStorageNotInitialized.Log();
// todo: Add IsResizable member
// if (!IsResizable) return ResultFs.SubStorageNotResizable.Log();