AGS: Fixed ScriptString could be serialized with wrong length

From upstream c00be4f9ee9501aebb0abc81ebbe5b4f2ffb0c0c
This commit is contained in:
Paul Gilbert 2022-05-05 19:59:34 -07:00
parent 28a2b6aa9c
commit 63c42d42c3
3 changed files with 35 additions and 28 deletions

View File

@ -34,9 +34,9 @@ DynObjectRef ScriptString::CreateString(const char *fromText) {
int ScriptString::Dispose(const char *address, bool force) {
// always dispose
if (text) {
free(text);
text = nullptr;
if (_text) {
free(_text);
_text = nullptr;
}
delete this;
return 1;
@ -50,29 +50,34 @@ size_t ScriptString::CalcSerializeSize() {
return _len + 1 + sizeof(int32_t);
}
void ScriptString::Serialize(const char *address, Stream *out) {
const auto *cstr = text ? text : "";
void ScriptString::Serialize(const char * /*address*/, Stream *out) {
const auto *cstr = _text ? _text : "";
out->WriteInt32(_len);
out->Write(cstr, _len + 1);
}
void ScriptString::Unserialize(int index, Stream *in, size_t data_sz) {
void ScriptString::Unserialize(int index, Stream *in, size_t /*data_sz*/) {
_len = in->ReadInt32();
text = (char *)malloc(_len + 1);
in->Read(text, _len + 1);
text[_len] = 0; // for safety
ccRegisterUnserializedObject(index, text, this);
_text = (char *)malloc(_len + 1);
in->Read(_text, _len + 1);
_text[_len] = 0; // for safety
ccRegisterUnserializedObject(index, _text, this);
}
ScriptString::ScriptString() {
text = nullptr;
_len = 0;
ScriptString::ScriptString(const char *text) {
_len = strlen(text);
_text = (char *)malloc(_len + 1);
memcpy(_text, text, _len + 1);
}
ScriptString::ScriptString(const char *fromText) {
_len = strlen(fromText);
text = (char *)malloc(_len + 1);
memcpy(text, fromText, _len + 1);
ScriptString::ScriptString(char *text, bool take_ownership) {
_len = strlen(text);
if (take_ownership) {
_text = text;
} else {
_text = (char *)malloc(_len + 1);
memcpy(_text, text, _len + 1);
}
}
} // namespace AGS3

View File

@ -27,18 +27,18 @@
namespace AGS3 {
struct ScriptString final : AGSCCDynamicObject, ICCStringClass {
// TODO: the preallocated text buffer may be assigned externally;
// find out if it's possible to refactor while keeping same functionality
char *text;
int Dispose(const char *address, bool force) override;
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
DynObjectRef CreateString(const char *fromText) override;
ScriptString();
ScriptString(const char *fromText);
ScriptString() = default;
ScriptString(const char *text);
ScriptString(char *text, bool take_ownership);
char *GetTextPtr() const {
return _text;
}
protected:
// Calculate and return required space for serialization, in bytes
@ -47,7 +47,10 @@ protected:
void Serialize(const char *address, AGS::Shared::Stream *out) override;
private:
size_t _len;
// TODO: the preallocated text buffer may be assigned externally;
// find out if it's possible to refactor while keeping same functionality
char *_text = nullptr;
size_t _len = 0;
};
} // namespace AGS3

View File

@ -255,11 +255,10 @@ DynObjectRef CreateNewScriptStringObj(const char *fromText, bool reAllocate) {
ScriptString *str;
if (reAllocate) {
str = new ScriptString(fromText);
} else {
str = new ScriptString();
str->text = const_cast<char *>(fromText);
} else { // TODO: refactor to avoid const casts!
str = new ScriptString((char *)fromText, true);
}
void *obj_ptr = str->text;
void *obj_ptr = str->GetTextPtr();
int32_t handle = ccRegisterManagedObject(obj_ptr, str);
if (handle == 0) {
delete str;