| 2393 | } |
| 2394 | |
| 2395 | bool read_string(u32 addr, u32 max_size, std::string& out_string, bool check_pages) noexcept |
| 2396 | { |
| 2397 | if (!max_size) |
| 2398 | { |
| 2399 | return true; |
| 2400 | } |
| 2401 | |
| 2402 | // Prevent overflow |
| 2403 | const u32 size = 0 - max_size < addr ? (0 - addr) : max_size; |
| 2404 | |
| 2405 | for (u32 i = addr, end = rx::alignUp(addr + size, 4096) - 1; i <= end;) |
| 2406 | { |
| 2407 | if (check_pages && !vm::check_addr(i, vm::page_readable)) |
| 2408 | { |
| 2409 | // Invalid string termination |
| 2410 | return false; |
| 2411 | } |
| 2412 | |
| 2413 | const char* s_start = vm::get_super_ptr<const char>(i); |
| 2414 | const u32 space = std::min<u32>(end - i + 1, 4096 - (i % 4096)); |
| 2415 | const char* s_end = s_start + space; |
| 2416 | const char* s_null = std::find(s_start, s_end, '\0'); |
| 2417 | |
| 2418 | // Append string |
| 2419 | out_string.append(s_start, s_null); |
| 2420 | |
| 2421 | // Recheck for zeroes after append |
| 2422 | const usz old_size = out_string.size(); |
| 2423 | out_string.erase(std::find(out_string.end() - (s_null - s_start), out_string.end(), '\0'), out_string.end()); |
| 2424 | |
| 2425 | if (out_string.size() != old_size || s_null != s_end) |
| 2426 | { |
| 2427 | // Null terminated |
| 2428 | return true; |
| 2429 | } |
| 2430 | |
| 2431 | i += space; |
| 2432 | |
| 2433 | if (!i) |
| 2434 | { |
| 2435 | break; |
| 2436 | } |
| 2437 | } |
| 2438 | |
| 2439 | // Non-null terminated but terminated by size limit (so the string may continue) |
| 2440 | return size == max_size; |
| 2441 | } |
| 2442 | } // namespace vm |
| 2443 | |
| 2444 | void fmt_class_string<vm::_ptr_base<const void, u32>>::format(std::string& out, u64 arg) |
no test coverage detected