fix(libSceNpCppWebApi): preserve Binary contents across aliasing and failure

This commit is contained in:
Eduardo Ruiz committed 2026-11-02 13:14:02 +01:00
1 parent 7c6bc61f56
commit bfeca4f439
2 files changed
+26 -9

No files matched your search

+16 -7
View File
@@ -1637,12 +1637,16 @@ static void ResetBinary(CommonBinary* self) {
}
static int SetBinary(CommonBinary* self, const void* data, const std::uint64_t size) {
ResetBinary(self);
if (size == 0) return 0;
if (size == 0) {
ResetBinary(self);
return 0;
}
if (data == nullptr) return BinaryInvalidArgument;
void* buffer = std::malloc(size);
if (size > SIZE_MAX) return BinaryOutOfMemory;
void* buffer = std::malloc(static_cast<std::size_t>(size));
if (buffer == nullptr) return BinaryOutOfMemory;
std::memcpy(buffer, data, size);
std::memcpy(buffer, data, static_cast<std::size_t>(size));
std::free(self->buffer);
self->buffer = buffer;
self->size = size;
return 0;
@@ -1651,11 +1655,16 @@ static int SetBinary(CommonBinary* self, const void* data, const std::uint64_t s
static int AppendBinary(CommonBinary* self, const void* data, const std::uint64_t size) {
if (size == 0) return 0;
if (data == nullptr) return BinaryInvalidArgument;
void* buffer = std::realloc(self->buffer, self->size + size);
if (size > UINT64_MAX - self->size) return BinaryOutOfMemory;
const std::uint64_t total = self->size + size;
if (total > SIZE_MAX) return BinaryOutOfMemory;
auto* buffer = static_cast<std::uint8_t*>(std::malloc(static_cast<std::size_t>(total)));
if (buffer == nullptr) return BinaryOutOfMemory;
std::memcpy(static_cast<std::uint8_t*>(buffer) + self->size, data, size);
if (self->size != 0) std::memcpy(buffer, self->buffer, static_cast<std::size_t>(self->size));
std::memcpy(buffer + static_cast<std::size_t>(self->size), data, static_cast<std::size_t>(size));
std::free(self->buffer);
self->buffer = buffer;
self->size += size;
self->size = total;
return 0;
}
+10 -2
View File
@@ -80,14 +80,22 @@ void TestSetAndAppend() {
Require(std::memcmp(_ZNK3sce2Np9CppWebApi6Common6Binary9getBinaryEv(reinterpret_cast<const CommonBinary*>(storage.bytes)), "abcde", 5) == 0);
Require(_ZN3sce2Np9CppWebApi6Common6Binary9setBinaryEPKvm(binary, nullptr, 1) == kInvalidArgument);
Require(Load<std::uint64_t>(storage, kDataSizeOffset) == 0);
Require(Load<void*>(storage, kBufferOffset) == nullptr);
Require(Load<std::uint64_t>(storage, kDataSizeOffset) == 5);
Require(std::memcmp(_ZNK3sce2Np9CppWebApi6Common6Binary9getBinaryEv(reinterpret_cast<const CommonBinary*>(storage.bytes)), "abcde", 5) == 0);
Require(_ZN3sce2Np9CppWebApi6Common6Binary9setBinaryEPKvm(binary, nullptr, 0) == 0);
Require(_ZN3sce2Np9CppWebApi6Common6Binary12appendBinaryEPKvm(binary, "xy", 2) == 0);
Require(Load<std::uint64_t>(storage, kDataSizeOffset) == 2);
Require(std::memcmp(_ZNK3sce2Np9CppWebApi6Common6Binary9getBinaryEv(reinterpret_cast<const CommonBinary*>(storage.bytes)), "xy", 2) == 0);
Require(_ZN3sce2Np9CppWebApi6Common6Binary9setBinaryEPKvm(binary, _ZNK3sce2Np9CppWebApi6Common6Binary9getBinaryEv(reinterpret_cast<const CommonBinary*>(storage.bytes)), 2) == 0);
Require(Load<std::uint64_t>(storage, kDataSizeOffset) == 2);
Require(std::memcmp(_ZNK3sce2Np9CppWebApi6Common6Binary9getBinaryEv(reinterpret_cast<const CommonBinary*>(storage.bytes)), "xy", 2) == 0);
Require(_ZN3sce2Np9CppWebApi6Common6Binary12appendBinaryEPKvm(binary, _ZNK3sce2Np9CppWebApi6Common6Binary9getBinaryEv(reinterpret_cast<const CommonBinary*>(storage.bytes)), 2) == 0);
Require(Load<std::uint64_t>(storage, kDataSizeOffset) == 4);
Require(std::memcmp(_ZNK3sce2Np9CppWebApi6Common6Binary9getBinaryEv(reinterpret_cast<const CommonBinary*>(storage.bytes)), "xyxy", 4) == 0);
Require(Load<std::int32_t>(storage, kReferenceCountOffset) == 0);
Require(_ZN3sce2Np9CppWebApi6Common6Binary21intrusive_ptr_add_refEPS3_(binary) == 1);
Require(_ZN3sce2Np9CppWebApi6Common6Binary21intrusive_ptr_add_refEPS3_(binary) == 2);