Implement sysutil_check_name_string

* Fully implement 3, 4, 16 and 17 error checks of cellSaveData.
* cellSysCacheMount restrict characters in ID.
* cellHddGameCheck restricts characters in dirName.
This commit is contained in:
Eladash 2019-11-08 18:40:46 +02:00 committed by Ivan
parent 7519e36317
commit 1986944c61
5 changed files with 134 additions and 9 deletions

View File

@ -150,13 +150,16 @@ error_code cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName
{
cellGame.error("cellHddGameCheck(version=%d, dirName=%s, errDialog=%d, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
std::string dir = dirName.get_ptr();
if (dir.size() != 9)
if (!dirName || !funcStat || sysutil_check_name_string(dirName.get_ptr(), 1, CELL_GAME_DIRNAME_SIZE) != 0)
{
return CELL_HDDGAME_ERROR_PARAM;
}
std::string dir = dirName.get_ptr();
// TODO: Find error code
verify(HERE), dir.size() == 9;
vm::var<CellHddGameCBResult> result;
vm::var<CellHddGameStatGet> get;
vm::var<CellHddGameStatSet> set;

View File

@ -240,12 +240,31 @@ static s32 savedata_check_args(u32 operation, u32 version, vm::cptr<char> dirNam
return 5;
}
if (operation <= SAVEDATA_OP_AUTO_LOAD && !dirName)
if (operation <= SAVEDATA_OP_AUTO_LOAD)
{
if (!dirName)
{
// ****** sysutil savedata parameter error : 2 ******
return 2;
}
switch (sysutil_check_name_string(dirName.get_ptr(), 1, CELL_SAVEDATA_DIRNAME_SIZE))
{
case -1:
{
// ****** sysutil savedata parameter error : 3 ******
return 3;
}
case -2:
{
// ****** sysutil savedata parameter error : 4 ******
return 4;
}
case 0: break;
default: ASSUME(0);
}
}
if ((operation >= SAVEDATA_OP_LIST_AUTO_SAVE && operation <= SAVEDATA_OP_FIXED_LOAD) || operation == SAVEDATA_OP_FIXED_DELETE)
{
if (!setList)
@ -279,7 +298,50 @@ static s32 savedata_check_args(u32 operation, u32 version, vm::cptr<char> dirNam
return 17;
}
// TODO: Theres some check here I've missed about dirNamePrefix
char cur, buf[CELL_SAVEDATA_DIRNAME_SIZE + 1]{};
for (s32 pos = 0, posprefix = 0; cur = setList->dirNamePrefix[pos++], true;)
{
if (cur == '\0' || cur == '|')
{
// Check prefix if not empty
if (posprefix)
{
switch (sysutil_check_name_string(buf, 1, CELL_SAVEDATA_DIRNAME_SIZE))
{
case -1:
{
// ****** sysutil savedata parameter error : 16 ******
return 16;
}
case -2:
{
// ****** sysutil savedata parameter error : 17 ******
return 17;
}
case 0: break;
default: ASSUME(0);
}
}
if (cur == '\0')
{
break;
}
// Note: no need to reset buffer, only position
posprefix = 0;
continue;
}
if (posprefix == CELL_SAVEDATA_DIRNAME_SIZE)
{
// ****** sysutil savedata parameter error : 17 ******
return 17;
}
buf[posprefix++] = cur;
}
if (setList->reserved)
{

View File

@ -115,13 +115,13 @@ error_code cellSysCacheMount(vm::ptr<CellSysCacheParam> param)
const auto cache = g_fxo->get<syscache_info>();
if (!param || !std::memchr(param->cacheId, '\0', CELL_SYSCACHE_ID_SIZE))
if (!param || (param->cacheId[0] && sysutil_check_name_string(param->cacheId, 1, CELL_SYSCACHE_ID_SIZE) != 0))
{
return CELL_SYSCACHE_ERROR_PARAM;
}
// Full virtualized cache id (with title id included)
std::string cache_id = vfs::escape(Emu.GetTitleID() + '_' + param->cacheId, true);
std::string cache_id = vfs::escape(Emu.GetTitleID() + '_' + param->cacheId);
// Full path to virtual cache root (/dev_hdd1)
std::string new_path = cache->cache_root + cache_id + '/';

View File

@ -3,6 +3,7 @@
#include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_process.h"
#include "cellSysutil.h"
#include "Utilities/StrUtil.h"
@ -134,6 +135,64 @@ void fmt_class_string<CellSysutilParamId>::format(std::string& out, u64 arg)
});
}
// Common string checks used in libsysutil functions
s32 sysutil_check_name_string(const char* src, s32 minlen, s32 maxlen)
{
s32 lastpos;
if (g_ps3_process_info.sdk_ver > 0x36FFFF)
{
// Limit null terminator boundary to before buffer max size
lastpos = std::max(maxlen - 1, 0);
}
else
{
// Limit null terminator boundary to one after buffer max size
lastpos = maxlen;
}
char cur = src[0];
if (cur == '_')
{
// Invalid character at start
return -1;
}
for (u32 index = 0;; cur = src[++index])
{
if (cur == '\0' || index == maxlen)
{
if (minlen > index || (maxlen == index && src[lastpos]))
{
// String length is invalid
return -2;
}
// OK
return 0;
}
if (cur >= 'A' && cur <= 'Z')
{
continue;
}
if (cur >= '0' && cur <= '9')
{
continue;
}
if (cur == '-' || cur == '_')
{
continue;
}
// Invalid character found
return -1;
}
}
s32 _cellSysutilGetSystemParamInt()
{
UNIMPLEMENTED_FUNC(cellSysutil);

View File

@ -204,3 +204,4 @@ struct CellSysCacheParam
extern void sysutil_register_cb(std::function<s32(ppu_thread&)>&&);
extern void sysutil_send_system_cmd(u64 status, u64 param);
s32 sysutil_check_name_string(const char* src, s32 minlen, s32 maxlen);