mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-09-08 19:12:56 +02:00
Fix some bugs and safety issues in sandbox memory manipulation functions
This commit is contained in:
parent
cfaba64211
commit
e22b2c6d5a
9 changed files with 136 additions and 189 deletions
|
@ -122,28 +122,24 @@ void binding_base::copy_memory_from(const void *ptr, wasm_size_t size, wasm_size
|
|||
}
|
||||
}
|
||||
|
||||
void *mkxp_sandbox::sandbox_ptr(struct w2c_ruby &instance, wasm_ptr_t address) noexcept {
|
||||
if (address >= instance.w2c_memory.size) {
|
||||
std::abort();
|
||||
}
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
return instance.w2c_memory.data + instance.w2c_memory.size - address;
|
||||
#else
|
||||
return instance.w2c_memory.data + address;
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
}
|
||||
|
||||
wasm_size_t mkxp_sandbox::sandbox_strlen(struct w2c_ruby &instance, wasm_ptr_t address) noexcept {
|
||||
const char *ptr = (char *)sandbox_ptr(instance, address);
|
||||
const char *ptr = &sandbox_ref<char>(instance, address);
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
wasm_size_t size = 0;
|
||||
while ((uint8_t *)ptr != instance.w2c_memory.data && *--ptr) {
|
||||
while (*ptr) {
|
||||
if ((uint8_t *)ptr == instance.w2c_memory.data) {
|
||||
std::abort();
|
||||
}
|
||||
++size;
|
||||
--ptr;
|
||||
}
|
||||
return size;
|
||||
#else
|
||||
const char *end = (const char *)std::memchr(ptr, 0, instance.w2c_memory.size - address);
|
||||
return ptr == nullptr ? instance.w2c_memory.size - address : end - ptr;
|
||||
if (ptr == nullptr) {
|
||||
std::abort();
|
||||
}
|
||||
return end - ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -151,62 +147,24 @@ struct sandbox_str_guard mkxp_sandbox::sandbox_str(struct w2c_ruby &instance, wa
|
|||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
std::string str;
|
||||
str.reserve(sandbox_strlen(instance, address));
|
||||
const char *ptr = (const char *)sandbox_ptr(instance, address);
|
||||
while ((uint8_t *)ptr != instance.w2c_memory.data && *--ptr) {
|
||||
for (const char *ptr = &sandbox_ref<char>(instance, address); *ptr; --ptr) {
|
||||
str.push_back(*ptr);
|
||||
}
|
||||
return str;
|
||||
#else
|
||||
if (instance.w2c_memory.size - address <= sandbox_strlen(instance, address)) {
|
||||
if (address >= instance.w2c_memory.size || instance.w2c_memory.size - address <= sandbox_strlen(instance, address)) {
|
||||
std::abort();
|
||||
}
|
||||
return (const char *)sandbox_ptr(instance, address);
|
||||
return &sandbox_ref<char>(instance, address);
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
}
|
||||
|
||||
void mkxp_sandbox::sandbox_strcpy(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src) noexcept {
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
char *dst = (char *)sandbox_ptr(instance, dst_address);
|
||||
while (*src) {
|
||||
if ((uint8_t *)dst == instance.w2c_memory.data) {
|
||||
std::abort();
|
||||
}
|
||||
*--dst = *src++;
|
||||
}
|
||||
*dst = 0;
|
||||
#else
|
||||
if (instance.w2c_memory.size - dst_address <= std::strlen(src)) {
|
||||
std::abort();
|
||||
}
|
||||
char *dst = (char *)sandbox_ptr(instance, dst_address);
|
||||
std::strcpy(dst, src);
|
||||
#endif
|
||||
sandbox_arycpy(instance, dst_address, src, (wasm_size_t)std::strlen(src) + 1);
|
||||
}
|
||||
|
||||
void mkxp_sandbox::sandbox_strncpy(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) noexcept {
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
char *dst = (char *)sandbox_ptr(instance, dst_address);
|
||||
while (max_size && *src) {
|
||||
if ((uint8_t *)dst == instance.w2c_memory.data) {
|
||||
std::abort();
|
||||
}
|
||||
*--dst = *src++;
|
||||
--max_size;
|
||||
}
|
||||
if (max_size) {
|
||||
*dst = 0;
|
||||
}
|
||||
#else
|
||||
if (instance.w2c_memory.size - dst_address <= std::strlen(src)) {
|
||||
std::abort();
|
||||
}
|
||||
char *dst = (char *)sandbox_ptr(instance, dst_address);
|
||||
std::strncpy(dst, src, max_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *binding_base::ptr(wasm_ptr_t address) const noexcept {
|
||||
return sandbox_ptr(instance(), address);
|
||||
void mkxp_sandbox::sandbox_strncpy_s(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) noexcept {
|
||||
sandbox_arycpy(instance, dst_address, src, std::min((wasm_size_t)std::strlen(src) + 1, max_size));
|
||||
}
|
||||
|
||||
wasm_size_t binding_base::strlen(wasm_ptr_t address) const noexcept {
|
||||
|
@ -221,8 +179,8 @@ void binding_base::strcpy(wasm_ptr_t dst_address, const char *src) const noexcep
|
|||
sandbox_strcpy(instance(), dst_address, src);
|
||||
}
|
||||
|
||||
void binding_base::strncpy(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept {
|
||||
sandbox_strncpy(instance(), dst_address, src, max_size);
|
||||
void binding_base::strncpy_s(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept {
|
||||
sandbox_strncpy_s(instance(), dst_address, src, max_size);
|
||||
}
|
||||
|
||||
binding_base::object::object() : ptr(nullptr), typenum(0) {}
|
||||
|
|
|
@ -151,11 +151,31 @@ namespace mkxp_sandbox {
|
|||
};
|
||||
|
||||
// Gets a pointer to the given address in sandbox memory.
|
||||
void *sandbox_ptr(struct w2c_ruby &instance, wasm_ptr_t address) noexcept;
|
||||
// Unlike `sandbox_ref`, the address does not need to be aligned.
|
||||
template <typename T> void *sandbox_ptr_unaligned(struct w2c_ruby &instance, wasm_ptr_t address) noexcept {
|
||||
static_assert(std::is_arithmetic<T>::value, "can only get references to numeric values in the sandbox");
|
||||
if (address + (wasm_ptr_t)sizeof(T) < address || address + (wasm_ptr_t)sizeof(T) > instance.w2c_memory.size) {
|
||||
std::abort();
|
||||
}
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
return instance.w2c_memory.data + instance.w2c_memory.size - address - sizeof(T);
|
||||
#else
|
||||
return instance.w2c_memory.data + address;
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
}
|
||||
|
||||
// Gets a pointer to the given index in the array at a given address in sandbox memory.
|
||||
// Unlike `sandbox_ref`, the address does not need to be aligned.
|
||||
template <typename T> void *sandbox_ptr_unaligned(struct w2c_ruby &instance, wasm_ptr_t array_address, wasm_size_t array_index) noexcept {
|
||||
if (array_address + array_index < array_address) {
|
||||
std::abort();
|
||||
}
|
||||
return sandbox_ptr_unaligned<T>(instance, array_address + array_index * sizeof(T));
|
||||
}
|
||||
|
||||
// Gets a reference to the value stored at a given address in sandbox memory.
|
||||
// Make sure the address is aligned, or this function will abort.
|
||||
template <typename T> T &sandbox_ref(struct w2c_ruby &instance, wasm_ptr_t address) noexcept {
|
||||
static_assert(std::is_arithmetic<T>::value, "can only get references to numeric values in the sandbox");
|
||||
if (address % sizeof(T) != 0) {
|
||||
#ifdef MKXPZ_RETRO_MEMORY64
|
||||
std::fprintf(stderr, "unaligned memory access of size %u at address 0x%016llx in `mkxp_sandbox::sandbox_ref()`\n", (unsigned int)sizeof(T), (unsigned long long)address);
|
||||
|
@ -165,16 +185,14 @@ namespace mkxp_sandbox {
|
|||
std::fflush(stderr);
|
||||
std::abort();
|
||||
}
|
||||
assert(address % sizeof(T) == 0);
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
return *(T *)sandbox_ptr(instance, address + sizeof(T));
|
||||
#else
|
||||
return *(T *)sandbox_ptr(instance, address);
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
return *(T *)sandbox_ptr_unaligned<T>(instance, address);
|
||||
}
|
||||
|
||||
// Gets a reference to the value stored at the given index in the array at a given address in sandbox memory.
|
||||
template <typename T> T &sandbox_ref(struct w2c_ruby &instance, wasm_ptr_t array_address, wasm_size_t array_index) noexcept {
|
||||
if (array_address + array_index < array_address) {
|
||||
std::abort();
|
||||
}
|
||||
return sandbox_ref<T>(array_address + array_index * sizeof(T));
|
||||
}
|
||||
|
||||
|
@ -218,26 +236,20 @@ namespace mkxp_sandbox {
|
|||
void sandbox_strcpy(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src) noexcept;
|
||||
|
||||
// Copies a string into a sandbox memory address.
|
||||
void sandbox_strncpy(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) noexcept;
|
||||
void sandbox_strncpy_s(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) noexcept;
|
||||
|
||||
// Copies an array of length `num_elements` into a sandbox memory address.
|
||||
template <typename T> void sandbox_arycpy(struct w2c_ruby &instance, wasm_ptr_t dst_address, const T *src, wasm_size_t num_elements) noexcept {
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
T *dst = (T *)sandbox_ptr(instance, dst_address);
|
||||
while (num_elements > 0) {
|
||||
if ((uint8_t *)dst - instance.w2c_memory.data < sizeof(T)) {
|
||||
std::abort();
|
||||
}
|
||||
*--dst = *src++;
|
||||
--num_elements;
|
||||
}
|
||||
#else
|
||||
if (instance.w2c_memory.size - dst_address < num_elements * sizeof(T)) {
|
||||
if (dst_address >= instance.w2c_memory.size || instance.w2c_memory.size - dst_address < num_elements * sizeof(T)) {
|
||||
std::abort();
|
||||
}
|
||||
T *dst = (T *)sandbox_ptr(instance, dst_address);
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
for (wasm_size_t i = 0; i < num_elements; ++i) {
|
||||
std::memcpy(sandbox_ptr_unaligned<T>(instance, dst_address, i), src + i, sizeof(T));
|
||||
}
|
||||
#else
|
||||
if (num_elements > 0) {
|
||||
std::memcpy(dst, src, num_elements * sizeof(T));
|
||||
std::memcpy(sandbox_ptr_unaligned<T>(instance, dst_address), src, num_elements * sizeof(T));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -351,14 +363,25 @@ namespace mkxp_sandbox {
|
|||
void copy_memory_from(const void *ptr, wasm_size_t size, wasm_size_t capacity, bool swap_bytes) noexcept;
|
||||
|
||||
// Gets a pointer to the given address in sandbox memory.
|
||||
void *ptr(wasm_ptr_t address) const noexcept;
|
||||
// Unlike `sandbox_ref`, the address does not need to be aligned.
|
||||
template <typename T> void *ptr_unaligned(wasm_ptr_t address) const noexcept {
|
||||
return sandbox_ptr_unaligned<T>(instance(), address);
|
||||
}
|
||||
|
||||
// Gets a pointer to the given index in the array at a given address in sandbox memory.
|
||||
// Unlike `sandbox_ref`, the address does not need to be aligned.
|
||||
template <typename T> void *ptr_unaligned(wasm_ptr_t array_address, wasm_size_t array_index) const noexcept {
|
||||
return sandbox_ptr_unaligned<T>(instance(), array_address, array_index);
|
||||
}
|
||||
|
||||
// Gets a reference to the value stored at a given address in sandbox memory.
|
||||
// Make sure the address is aligned, or this function will abort.
|
||||
template <typename T> T &ref(wasm_ptr_t address) const noexcept {
|
||||
return sandbox_ref<T>(instance(), address);
|
||||
}
|
||||
|
||||
// Gets a reference to the value stored at the given index in the array at a given address in sandbox memory.
|
||||
// Make sure the address is aligned, or this function will abort.
|
||||
template <typename T> T &ref(wasm_ptr_t array_address, wasm_size_t array_index) const noexcept {
|
||||
return ref<T>(array_address + array_index * sizeof(T));
|
||||
}
|
||||
|
@ -373,7 +396,7 @@ namespace mkxp_sandbox {
|
|||
void strcpy(wasm_ptr_t dst_address, const char *src) const noexcept;
|
||||
|
||||
// Copies a string into a sandbox memory address.
|
||||
void strncpy(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept;
|
||||
void strncpy_s(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept;
|
||||
|
||||
// Copies an array of length `num_elements` into a sandbox memory address.
|
||||
template <typename T> void arycpy(wasm_ptr_t dst_address, const T *src, wasm_size_t num_elements) const noexcept {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include "bitmap-binding.h"
|
||||
#include "disposable-binding.h"
|
||||
#include "etc-binding.h"
|
||||
|
@ -406,7 +407,12 @@ static VALUE get_raw_data(VALUE self) {
|
|||
SANDBOX_AWAIT_S(1, rb_str_new_cstr, "");
|
||||
SANDBOX_AWAIT(rb_str_resize, SANDBOX_SLOT(1), SANDBOX_SLOT(2));
|
||||
SANDBOX_AWAIT_S(0, rb_string_value_ptr, &SANDBOX_SLOT(1));
|
||||
SANDBOX_GUARD_L(bitmap->getRaw(sb().e, sb()->ptr(SANDBOX_SLOT(0)), SANDBOX_SLOT(2)));
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
SANDBOX_GUARD_L(bitmap->getRaw(sb().e, &sb()->ref<uint8_t>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(2), (int32_t)1) - 1), SANDBOX_SLOT(2)));
|
||||
std::reverse(&sb()->ref<uint8_t>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(2), (int32_t)1) - 1), &sb()->ref<uint8_t>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(2), (int32_t)1) - 1) + SANDBOX_SLOT(2));
|
||||
#else
|
||||
SANDBOX_GUARD_L(bitmap->getRaw(sb().e, &sb()->ref<uint8_t>(SANDBOX_SLOT(0)), SANDBOX_SLOT(2)));
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
}
|
||||
|
||||
return SANDBOX_SLOT(1);
|
||||
|
@ -418,13 +424,18 @@ static VALUE get_raw_data(VALUE self) {
|
|||
|
||||
static VALUE set_raw_data(VALUE self, VALUE value) {
|
||||
struct coro : boost::asio::coroutine {
|
||||
typedef decl_slots<wasm_ptr_t, wasm_size_t> slots;
|
||||
typedef decl_slots<wasm_ptr_t, int32_t> slots;
|
||||
|
||||
VALUE operator()(VALUE self, VALUE value) {
|
||||
BOOST_ASIO_CORO_REENTER (this) {
|
||||
SANDBOX_AWAIT_S(0, rb_string_value_ptr, &value);
|
||||
SANDBOX_AWAIT_S(1, get_bytesize, value);
|
||||
SANDBOX_GUARD_L(get_private_data<Bitmap>(self)->replaceRaw(sb().e, sb()->ptr(SANDBOX_SLOT(0)), SANDBOX_SLOT(1)));
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
SANDBOX_GUARD_L(get_private_data<Bitmap>(self)->replaceRaw(sb().e, &sb()->ref<uint8_t>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (int32_t)1) - 1), SANDBOX_SLOT(1)));
|
||||
std::reverse(&sb()->ref<uint8_t>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (int32_t)1) - 1), &sb()->ref<uint8_t>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (int32_t)1) - 1) + SANDBOX_SLOT(1));
|
||||
#else
|
||||
SANDBOX_GUARD_L(get_private_data<Bitmap>(self)->replaceRaw(sb().e, &sb()->ref<uint8_t>(SANDBOX_SLOT(0)), SANDBOX_SLOT(1)));
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
}
|
||||
|
||||
return self;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#ifndef MKXPZ_SANDBOX_SERIALIZABLE_BINDING_H
|
||||
#define MKXPZ_SANDBOX_SERIALIZABLE_BINDING_H
|
||||
|
||||
#include <algorithm>
|
||||
#include "binding-util.h"
|
||||
|
||||
namespace mkxp_sandbox {
|
||||
|
@ -34,7 +35,12 @@ namespace mkxp_sandbox {
|
|||
SANDBOX_AWAIT_S(2, rb_obj_alloc, klass);
|
||||
SANDBOX_AWAIT_S(0, rb_string_value_ptr, &src);
|
||||
SANDBOX_AWAIT_S(1, get_bytesize, src);
|
||||
SANDBOX_GUARD(set_private_data(sb().e, SANDBOX_SLOT(2), C::deserialize(sb().e, (const char *)sb()->ptr(SANDBOX_SLOT(0)), SANDBOX_SLOT(1))));
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
SANDBOX_GUARD(set_private_data(sb().e, SANDBOX_SLOT(2), C::deserialize(sb().e, &sb()->ref<char>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1), SANDBOX_SLOT(1))));
|
||||
std::reverse(&sb()->ref<char>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1), &sb()->ref<char>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1) + SANDBOX_SLOT(1));
|
||||
#else
|
||||
SANDBOX_GUARD(set_private_data(sb().e, SANDBOX_SLOT(2), C::deserialize(sb().e, &sb()->ref<char>(SANDBOX_SLOT(0)), SANDBOX_SLOT(1))));
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
}
|
||||
|
||||
return SANDBOX_SLOT(2);
|
||||
|
@ -54,7 +60,12 @@ namespace mkxp_sandbox {
|
|||
SANDBOX_AWAIT_S(2, rb_str_new_cstr, "");
|
||||
SANDBOX_AWAIT(rb_str_resize, SANDBOX_SLOT(2), SANDBOX_SLOT(1));
|
||||
SANDBOX_AWAIT_S(0, rb_string_value_ptr, &SANDBOX_SLOT(2));
|
||||
get_private_data<C>(self)->serialize((char *)sb()->ptr(SANDBOX_SLOT(0)));
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
get_private_data<C>(self)->serialize(&sb()->ref<char>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1));
|
||||
std::reverse(&sb()->ref<char>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1), &sb()->ref<char>(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1) + SANDBOX_SLOT(1));
|
||||
#else
|
||||
get_private_data<C>(self)->serialize(&sb()->ref<char>(SANDBOX_SLOT(0)));
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
}
|
||||
|
||||
return SANDBOX_SLOT(2);
|
||||
|
|
|
@ -138,10 +138,6 @@ void wasi_t::deallocate_file_descriptor(uint32_t fd) {
|
|||
}
|
||||
}
|
||||
|
||||
void *wasi_t::ptr(wasm_ptr_t address) const noexcept {
|
||||
return sandbox_ptr(*ruby, address);
|
||||
}
|
||||
|
||||
wasm_size_t wasi_t::strlen(wasm_ptr_t address) const noexcept {
|
||||
return sandbox_strlen(*ruby, address);
|
||||
}
|
||||
|
@ -150,8 +146,8 @@ void wasi_t::strcpy(wasm_ptr_t dst_address, const char *src) const noexcept {
|
|||
sandbox_strcpy(*ruby, dst_address, src);
|
||||
}
|
||||
|
||||
void wasi_t::strncpy(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept {
|
||||
sandbox_strncpy(*ruby, dst_address, src, max_size);
|
||||
void wasi_t::strncpy_s(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept {
|
||||
sandbox_strncpy_s(*ruby, dst_address, src, max_size);
|
||||
}
|
||||
|
||||
struct mkxp_sandbox::sandbox_str_guard wasi_t::str(wasm_ptr_t address) const noexcept {
|
||||
|
@ -550,7 +546,7 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_prestat_dir_name(wasi_t *was
|
|||
return WASI_EBADF;
|
||||
|
||||
case wasi_fd_type::FS:
|
||||
wasi->strncpy(path, wasi->fdtable[fd].dir_handle()->path.c_str(), path_len + 1);
|
||||
wasi->strncpy_s(path, wasi->fdtable[fd].dir_handle()->path.c_str(), path_len + 1);
|
||||
return WASI_ESUCCESS;
|
||||
|
||||
case wasi_fd_type::STDIN:
|
||||
|
@ -621,17 +617,21 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_read(wasi_t *wasi, uint32_t
|
|||
{
|
||||
uint32_t size = 0;
|
||||
while (iovs_len > 0) {
|
||||
uint8_t *ptr = (uint8_t *)wasi->ptr(wasi->ref<uint32_t>(iovs));
|
||||
uint32_t ptr = wasi->ref<uint32_t>(iovs);
|
||||
uint32_t length = wasi->ref<uint32_t>(iovs + 4);
|
||||
if (length > 0) {
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
ptr -= length;
|
||||
uint8_t *buffer = &wasi->ref<uint8_t>(ptr, length - 1);
|
||||
#else
|
||||
uint8_t *buffer = &wasi->ref<uint8_t>(ptr);
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
PHYSFS_sint64 n = PHYSFS_readBytes(wasi->fdtable[fd].file_handle()->file.get(), ptr, length);
|
||||
PHYSFS_sint64 n = PHYSFS_readBytes(wasi->fdtable[fd].file_handle()->file.get(), buffer, length);
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
std::reverse(ptr, ptr + length);
|
||||
std::reverse(buffer, buffer + length);
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
if (n < 0) return WASI_EIO;
|
||||
size += n;
|
||||
if (n < 0) return WASI_EIO;
|
||||
size += n;
|
||||
}
|
||||
iovs += 8;
|
||||
--iovs_len;
|
||||
}
|
||||
|
@ -694,29 +694,13 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_readdir(wasi_t *wasi, uint32
|
|||
if (edata->buf - edata->original_buf + 8 > edata->buf_len) {
|
||||
return PHYSFS_ENUM_STOP;
|
||||
}
|
||||
std::memcpy(
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
wasi->ptr(edata->buf + 8),
|
||||
#else
|
||||
wasi->ptr(edata->buf),
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
&edata->cookie,
|
||||
8
|
||||
);
|
||||
std::memcpy(wasi->ptr_unaligned<uint64_t>(edata->buf), &edata->cookie, 8);
|
||||
edata->buf += 8;
|
||||
|
||||
if (edata->buf - edata->original_buf + 8 > edata->buf_len) {
|
||||
return PHYSFS_ENUM_STOP;
|
||||
}
|
||||
std::memset(
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
wasi->ptr(edata->buf + 8),
|
||||
#else
|
||||
wasi->ptr(edata->buf),
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
0,
|
||||
8
|
||||
);
|
||||
std::memset(wasi->ptr_unaligned<uint64_t>(edata->buf), 0, 8);
|
||||
edata->buf += 8;
|
||||
|
||||
if (edata->buf - edata->original_buf + 4 > edata->buf_len) {
|
||||
|
@ -724,15 +708,7 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_readdir(wasi_t *wasi, uint32
|
|||
}
|
||||
{
|
||||
const uint32_t value = std::strlen(filename);
|
||||
std::memcpy(
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
wasi->ptr(edata->buf + 8),
|
||||
#else
|
||||
wasi->ptr(edata->buf),
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
&value,
|
||||
4
|
||||
);
|
||||
std::memcpy(wasi->ptr_unaligned<uint32_t>(edata->buf), &value, 4);
|
||||
}
|
||||
edata->buf += 4;
|
||||
|
||||
|
@ -908,18 +884,21 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_write(wasi_t *wasi, uint32_t
|
|||
}
|
||||
uint32_t size = 0;
|
||||
while (iovs_len > 0) {
|
||||
uint8_t *ptr = (uint8_t *)wasi->ptr(wasi->ref<uint32_t>(iovs));
|
||||
uint32_t ptr = wasi->ref<uint32_t>(iovs);
|
||||
uint32_t length = wasi->ref<uint32_t>(iovs + 4);
|
||||
if (length > 0) {
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
ptr -= length;
|
||||
std::reverse(ptr, ptr + length);
|
||||
uint8_t *buffer = &wasi->ref<uint8_t>(ptr, length - 1);
|
||||
#else
|
||||
uint8_t *buffer = &wasi->ref<uint8_t>(ptr);
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
PHYSFS_sint64 n = PHYSFS_writeBytes(wasi->fdtable[fd].file_handle()->file.get_write(), ptr, length);
|
||||
PHYSFS_sint64 n = PHYSFS_writeBytes(wasi->fdtable[fd].file_handle()->file.get_write(), buffer, length);
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
std::reverse(ptr, ptr + length);
|
||||
std::reverse(buffer, buffer + length);
|
||||
#endif // MKXPZ_BIG_ENDIAN
|
||||
if (n >= 0) {
|
||||
size += n;
|
||||
if (n > 0) {
|
||||
size += n;
|
||||
}
|
||||
}
|
||||
iovs += 8;
|
||||
--iovs_len;
|
||||
|
|
|
@ -210,14 +210,25 @@ typedef struct w2c_wasi__snapshot__preview1 {
|
|||
void deallocate_file_descriptor(uint32_t fd);
|
||||
|
||||
// Gets a pointer to the given address in sandbox memory.
|
||||
void *ptr(mkxp_sandbox::wasm_ptr_t address) const noexcept;
|
||||
// Unlike `sandbox_ref`, the address does not need to be aligned.
|
||||
template <typename T> void *ptr_unaligned(mkxp_sandbox::wasm_ptr_t address) const noexcept {
|
||||
return mkxp_sandbox::sandbox_ptr_unaligned<T>(*ruby, address);
|
||||
}
|
||||
|
||||
// Gets a pointer to the given index in the array at a given address in sandbox memory.
|
||||
// Unlike `sandbox_ref`, the address does not need to be aligned.
|
||||
template <typename T> void *ptr_unaligned(mkxp_sandbox::wasm_ptr_t array_address, mkxp_sandbox::wasm_size_t array_index) const noexcept {
|
||||
return mkxp_sandbox::sandbox_ptr_unaligned<T>(*ruby, array_address, array_index);
|
||||
}
|
||||
|
||||
// Gets a reference to the value stored at a given address in sandbox memory.
|
||||
// Make sure the address is aligned, or this function will abort.
|
||||
template <typename T> T &ref(mkxp_sandbox::wasm_ptr_t address) const noexcept {
|
||||
return mkxp_sandbox::sandbox_ref<T>(*ruby, address);
|
||||
}
|
||||
|
||||
// Gets a reference to the value stored at the given index in the array at a given address in sandbox memory.
|
||||
// Make sure the address is aligned, or this function will abort.
|
||||
template <typename T> T &ref(mkxp_sandbox::wasm_ptr_t array_address, mkxp_sandbox::wasm_size_t array_index) const noexcept {
|
||||
return ref<T>(array_address + array_index * sizeof(T));
|
||||
}
|
||||
|
@ -232,7 +243,7 @@ typedef struct w2c_wasi__snapshot__preview1 {
|
|||
void strcpy(mkxp_sandbox::wasm_ptr_t dst_address, const char *src) const noexcept;
|
||||
|
||||
// Copies a string into a sandbox memory address.
|
||||
void strncpy(mkxp_sandbox::wasm_ptr_t dst_address, const char *src, mkxp_sandbox::wasm_size_t max_size) const noexcept;
|
||||
void strncpy_s(mkxp_sandbox::wasm_ptr_t dst_address, const char *src, mkxp_sandbox::wasm_size_t max_size) const noexcept;
|
||||
|
||||
// Copies an array of length `num_elements` into a sandbox memory address.
|
||||
template <typename T> void arycpy(mkxp_sandbox::wasm_ptr_t dst_address, const T *src, mkxp_sandbox::wasm_size_t num_elements) const noexcept {
|
||||
|
|
|
@ -2306,10 +2306,6 @@ bool Bitmap::getRaw(Exception &exception, void *output, int output_size)
|
|||
Debug() << "GAME BUG: Game is calling getRaw on low-res Bitmap; you may want to patch the game to improve graphics quality.";
|
||||
}
|
||||
|
||||
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
output = (uint8_t *)output - output_size;
|
||||
#endif
|
||||
|
||||
if (!p->animation.enabled && (p->surface || p->megaSurface)) {
|
||||
void *src = (p->megaSurface) ? p->megaSurface->pixels : p->surface->pixels;
|
||||
memcpy(output, src, output_size);
|
||||
|
@ -2319,10 +2315,6 @@ bool Bitmap::getRaw(Exception &exception, void *output, int output_size)
|
|||
gl.ReadPixels(0,0,width(),height(),GL_RGBA,GL_UNSIGNED_BYTE,output);
|
||||
}
|
||||
|
||||
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
std::reverse((uint8_t *)output, (uint8_t *)output + output_size);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2345,18 +2337,9 @@ void Bitmap::replaceRaw(Exception &exception, void *pixel_data, int size)
|
|||
return;
|
||||
}
|
||||
|
||||
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
pixel_data = (uint8_t *)pixel_data - size;
|
||||
std::reverse((uint8_t *)pixel_data, (uint8_t *)pixel_data + size);
|
||||
#endif
|
||||
|
||||
TEX::bind(getGLTypes().tex);
|
||||
TEX::uploadImage(w, h, pixel_data, GL_RGBA);
|
||||
|
||||
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
std::reverse((uint8_t *)pixel_data, (uint8_t *)pixel_data + size);
|
||||
#endif
|
||||
|
||||
#ifdef MKXPZ_RETRO
|
||||
p->pushDiff(pixel_data, rect());
|
||||
#endif // MKXPZ_RETRO
|
||||
|
|
|
@ -129,13 +129,8 @@ void Table::serialize(char *buffer) const
|
|||
writeInt32(&buffer, zs);
|
||||
writeInt32(&buffer, size);
|
||||
|
||||
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
for (const int16_t datum : data)
|
||||
*(int16_t *)(buffer -= sizeof(int16_t)) = datum;
|
||||
#else
|
||||
if (size > 0)
|
||||
memcpy(buffer, dataPtr(data), sizeof(int16_t)*size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -167,13 +162,8 @@ Table *Table::deserialize(Exception &exception, const char *data, int len)
|
|||
|
||||
Table *t = new Table(x, y, z);
|
||||
|
||||
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
for (int16_t &datum : t->data)
|
||||
datum = *(int16_t *)(data -= sizeof(int16_t));
|
||||
#else
|
||||
if (size > 0)
|
||||
memcpy(dataPtr(t->data), data, sizeof(int16_t)*size);
|
||||
#endif
|
||||
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -31,15 +31,10 @@ readInt32(const char **dataP)
|
|||
{
|
||||
int32_t result;
|
||||
|
||||
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
*dataP -= 4;
|
||||
memcpy(&result, *dataP, 4);
|
||||
#else
|
||||
memcpy(&result, *dataP, 4);
|
||||
*dataP += 4;
|
||||
#endif
|
||||
|
||||
#if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
# ifdef _MSC_VER
|
||||
static_assert(sizeof(unsigned long) == sizeof(int32_t), "unsigned long should be 32 bits");
|
||||
result = (int32_t)_byteswap_ulong((unsigned long)result);
|
||||
|
@ -54,7 +49,7 @@ readInt32(const char **dataP)
|
|||
static inline double
|
||||
readDouble(const char **dataP)
|
||||
{
|
||||
#if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
uint64_t result;
|
||||
|
||||
memcpy(&result, *dataP, 8);
|
||||
|
@ -70,13 +65,8 @@ readDouble(const char **dataP)
|
|||
#else
|
||||
double result;
|
||||
|
||||
# if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
*dataP -= 8;
|
||||
memcpy(&result, *dataP, 8);
|
||||
# else
|
||||
memcpy(&result, *dataP, 8);
|
||||
*dataP += 8;
|
||||
# endif
|
||||
|
||||
return result;
|
||||
#endif
|
||||
|
@ -85,7 +75,7 @@ readDouble(const char **dataP)
|
|||
static inline void
|
||||
writeInt32(char **dataP, int32_t value)
|
||||
{
|
||||
#if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
# ifdef _MSC_VER
|
||||
static_assert(sizeof(unsigned long) == sizeof(int32_t), "unsigned long should be 32 bits");
|
||||
value = (int32_t)_byteswap_ulong((unsigned long)value);
|
||||
|
@ -94,19 +84,14 @@ writeInt32(char **dataP, int32_t value)
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
*dataP -= 4;
|
||||
memcpy(*dataP, &value, 4);
|
||||
#else
|
||||
memcpy(*dataP, &value, 4);
|
||||
*dataP += 4;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
writeDouble(char **dataP, double value)
|
||||
{
|
||||
#if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
#ifdef MKXPZ_BIG_ENDIAN
|
||||
uint64_t valueUint = *(uint64_t *)&value;
|
||||
|
||||
# ifdef _MSC_VER
|
||||
|
@ -116,14 +101,10 @@ writeDouble(char **dataP, double value)
|
|||
# endif
|
||||
|
||||
memcpy(*dataP, &valueUint, 8);
|
||||
*dataP += 8;
|
||||
#elif defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
|
||||
*dataP -= 8;
|
||||
memcpy(*dataP, &value, 8);
|
||||
#else
|
||||
memcpy(*dataP, &value, 8);
|
||||
*dataP += 8;
|
||||
#endif
|
||||
*dataP += 8;
|
||||
}
|
||||
|
||||
#endif // SERIALUTIL_H
|
||||
|
|
Loading…
Add table
Reference in a new issue