@@ -311,6 +311,43 @@ fs::file lv2_file::make_view(const std::shared_ptr<lv2_file>& _file, u64 offset)
311
311
return result;
312
312
}
313
313
314
+ std::pair<CellError, std::string_view> translate_to_sv (vm::cptr<char > ptr)
315
+ {
316
+ const u32 addr = ptr.addr ();
317
+
318
+ if (!vm::check_addr (addr, vm::page_readable))
319
+ {
320
+ return {CELL_EFAULT, {}};
321
+ }
322
+
323
+ const usz remained_page_memory = (~addr % 4096 ) + 1 ;
324
+
325
+ constexpr usz max_length = CELL_FS_MAX_FS_PATH_LENGTH + 1 ;
326
+
327
+ const usz target_memory_span_size = std::min<usz>(max_length, vm::check_addr (addr + 4096 , vm::page_readable) ? max_length : remained_page_memory);
328
+
329
+ std::string_view path{ptr.get_ptr (), target_memory_span_size};
330
+ path = path.substr (0 , path.find_first_of (' \0 ' ));
331
+
332
+ if (path.size () == max_length)
333
+ {
334
+ return {CELL_ENAMETOOLONG, {}};
335
+ }
336
+
337
+ if (path.size () == target_memory_span_size)
338
+ {
339
+ // Null character lookup has ended whilst pointing at invalid memory
340
+ return {CELL_EFAULT, path};
341
+ }
342
+
343
+ if (!path.starts_with (" /" sv))
344
+ {
345
+ return {CELL_ENOENT, path};
346
+ }
347
+
348
+ return {{}, path};
349
+ }
350
+
314
351
error_code sys_fs_test (ppu_thread&, u32 arg1, u32 arg2, vm::ptr<u32> arg3, u32 arg4, vm::ptr<char > buf, u32 buf_size)
315
352
{
316
353
sys_fs.trace (" sys_fs_test(arg1=0x%x, arg2=0x%x, arg3=*0x%x, arg4=0x%x, buf=*0x%x, buf_size=0x%x)" , arg1, arg2, arg3, arg4, buf, buf_size);
@@ -600,10 +637,14 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr<char> path, s32 flags, vm::ptr<
600
637
601
638
sys_fs.warning (" sys_fs_open(path=%s, flags=%#o, fd=*0x%x, mode=%#o, arg=*0x%x, size=0x%llx)" , path, flags, fd, mode, arg, size);
602
639
603
- if (!path)
604
- return CELL_EFAULT;
640
+ const auto [path_error, vpath] = translate_to_sv (path);
605
641
606
- auto [error, ppath, real, file, type] = lv2_file::open (path.get_ptr (), flags, mode, arg.get_ptr (), size);
642
+ if (path_error)
643
+ {
644
+ return {path_error, vpath};
645
+ }
646
+
647
+ auto [error, ppath, real, file, type] = lv2_file::open (vpath, flags, mode, arg.get_ptr (), size);
607
648
608
649
if (error)
609
650
{
@@ -849,15 +890,15 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u32> fd)
849
890
850
891
sys_fs.warning (" sys_fs_opendir(path=%s, fd=*0x%x)" , path, fd);
851
892
852
- if (!path)
853
- return CELL_EFAULT;
893
+ const auto [path_error, vpath] = translate_to_sv (path);
854
894
855
- if (!path[0 ])
856
- return CELL_ENOENT;
895
+ if (path_error)
896
+ {
897
+ return {path_error, vpath};
898
+ }
857
899
858
900
std::string processed_path;
859
901
std::vector<std::string> ext;
860
- const std::string_view vpath = path.get_ptr ();
861
902
const std::string local_path = vfs::get (vpath, &ext, &processed_path);
862
903
863
904
processed_path += " /" ;
@@ -1018,13 +1059,13 @@ error_code sys_fs_stat(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<CellFsStat>
1018
1059
1019
1060
sys_fs.warning (" sys_fs_stat(path=%s, sb=*0x%x)" , path, sb);
1020
1061
1021
- if (!path)
1022
- return CELL_EFAULT;
1062
+ const auto [path_error, vpath] = translate_to_sv (path);
1023
1063
1024
- if (!path[0 ])
1025
- return CELL_ENOENT;
1064
+ if (path_error)
1065
+ {
1066
+ return {path_error, vpath};
1067
+ }
1026
1068
1027
- const std::string_view vpath = path.get_ptr ();
1028
1069
const std::string local_path = vfs::get (vpath);
1029
1070
1030
1071
const auto mp = lv2_fs_object::get_mp (vpath);
@@ -1168,13 +1209,13 @@ error_code sys_fs_mkdir(ppu_thread& ppu, vm::cptr<char> path, s32 mode)
1168
1209
1169
1210
sys_fs.warning (" sys_fs_mkdir(path=%s, mode=%#o)" , path, mode);
1170
1211
1171
- if (!path)
1172
- return CELL_EFAULT;
1212
+ const auto [path_error, vpath] = translate_to_sv (path);
1173
1213
1174
- if (!path[0 ])
1175
- return CELL_ENOENT;
1214
+ if (path_error)
1215
+ {
1216
+ return {path_error, vpath};
1217
+ }
1176
1218
1177
- const std::string_view vpath = path.get_ptr ();
1178
1219
const std::string local_path = vfs::get (vpath);
1179
1220
1180
1221
const auto mp = lv2_fs_object::get_mp (vpath);
@@ -1219,10 +1260,21 @@ error_code sys_fs_rename(ppu_thread& ppu, vm::cptr<char> from, vm::cptr<char> to
1219
1260
1220
1261
sys_fs.warning (" sys_fs_rename(from=%s, to=%s)" , from, to);
1221
1262
1222
- const std::string_view vfrom = from.get_ptr ();
1223
- const std::string local_from = vfs::get (vfrom);
1263
+ const auto [from_error, vfrom] = translate_to_sv (from);
1264
+
1265
+ if (from_error)
1266
+ {
1267
+ return {from_error, vfrom};
1268
+ }
1224
1269
1225
- const std::string_view vto = to.get_ptr ();
1270
+ const auto [to_error, vto] = translate_to_sv (to);
1271
+
1272
+ if (to_error)
1273
+ {
1274
+ return {to_error, vto};
1275
+ }
1276
+
1277
+ const std::string local_from = vfs::get (vfrom);
1226
1278
const std::string local_to = vfs::get (vto);
1227
1279
1228
1280
const auto mp = lv2_fs_object::get_mp (vfrom);
@@ -1274,13 +1326,13 @@ error_code sys_fs_rmdir(ppu_thread& ppu, vm::cptr<char> path)
1274
1326
1275
1327
sys_fs.warning (" sys_fs_rmdir(path=%s)" , path);
1276
1328
1277
- if (!path)
1278
- return CELL_EFAULT;
1329
+ const auto [path_error, vpath] = translate_to_sv (path);
1279
1330
1280
- if (!path[0 ])
1281
- return CELL_ENOENT;
1331
+ if (path_error)
1332
+ {
1333
+ return {path_error, vpath};
1334
+ }
1282
1335
1283
- const std::string_view vpath = path.get_ptr ();
1284
1336
const std::string local_path = vfs::get (vpath);
1285
1337
1286
1338
const auto mp = lv2_fs_object::get_mp (vpath);
@@ -1325,13 +1377,13 @@ error_code sys_fs_unlink(ppu_thread& ppu, vm::cptr<char> path)
1325
1377
1326
1378
sys_fs.warning (" sys_fs_unlink(path=%s)" , path);
1327
1379
1328
- if (!path)
1329
- return CELL_EFAULT;
1380
+ const auto [path_error, vpath] = translate_to_sv (path);
1330
1381
1331
- if (!path[0 ])
1332
- return CELL_ENOENT;
1382
+ if (path_error)
1383
+ {
1384
+ return {path_error, vpath};
1385
+ }
1333
1386
1334
- const std::string_view vpath = path.get_ptr ();
1335
1387
const std::string local_path = vfs::get (vpath);
1336
1388
1337
1389
const auto mp = lv2_fs_object::get_mp (vpath);
@@ -2002,13 +2054,13 @@ error_code sys_fs_get_block_size(ppu_thread& ppu, vm::cptr<char> path, vm::ptr<u
2002
2054
2003
2055
sys_fs.warning (" sys_fs_get_block_size(path=%s, sector_size=*0x%x, block_size=*0x%x, arg4=*0x%x)" , path, sector_size, block_size, arg4);
2004
2056
2005
- if (!path)
2006
- return CELL_EFAULT;
2057
+ const auto [path_error, vpath] = translate_to_sv (path);
2007
2058
2008
- if (!path[0 ])
2009
- return CELL_ENOENT;
2059
+ if (path_error)
2060
+ {
2061
+ return {path_error, vpath};
2062
+ }
2010
2063
2011
- const std::string_view vpath = path.get_ptr ();
2012
2064
const std::string local_path = vfs::get (vpath);
2013
2065
2014
2066
if (vpath.find_first_not_of (' /' ) == umax)
@@ -2056,13 +2108,13 @@ error_code sys_fs_truncate(ppu_thread& ppu, vm::cptr<char> path, u64 size)
2056
2108
2057
2109
sys_fs.warning (" sys_fs_truncate(path=%s, size=0x%llx)" , path, size);
2058
2110
2059
- if (!path)
2060
- return CELL_EFAULT;
2111
+ const auto [path_error, vpath] = translate_to_sv (path);
2061
2112
2062
- if (!path[0 ])
2063
- return CELL_ENOENT;
2113
+ if (path_error)
2114
+ {
2115
+ return {path_error, vpath};
2116
+ }
2064
2117
2065
- const std::string_view vpath = path.get_ptr ();
2066
2118
const std::string local_path = vfs::get (vpath);
2067
2119
2068
2120
const auto mp = lv2_fs_object::get_mp (vpath);
@@ -2249,13 +2301,13 @@ error_code sys_fs_utime(ppu_thread& ppu, vm::cptr<char> path, vm::cptr<CellFsUti
2249
2301
sys_fs.warning (" sys_fs_utime(path=%s, timep=*0x%x)" , path, timep);
2250
2302
sys_fs.warning (" ** actime=%u, modtime=%u" , timep->actime , timep->modtime );
2251
2303
2252
- if (!path)
2253
- return CELL_EFAULT;
2304
+ const auto [path_error, vpath] = translate_to_sv (path);
2254
2305
2255
- if (!path[0 ])
2256
- return CELL_ENOENT;
2306
+ if (path_error)
2307
+ {
2308
+ return {path_error, vpath};
2309
+ }
2257
2310
2258
- const std::string_view vpath = path.get_ptr ();
2259
2311
const std::string local_path = vfs::get (vpath);
2260
2312
2261
2313
const auto mp = lv2_fs_object::get_mp (vpath);
0 commit comments