Skip to content

Commit

Permalink
AGS: Make NumberPtr a class instead of a union
Browse files Browse the repository at this point in the history
It's illegal to reference an inactive member of a union and the types
are not layout compatible (and even not of the same size).
Instead, store every value in a integer of pointer size and cast
pointers to and from it.
This should really fix bug #13557.
  • Loading branch information
lephilousophe committed Nov 16, 2024
1 parent 1c622ce commit 25cbcf1
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 19 deletions.
6 changes: 3 additions & 3 deletions engines/ags/engine/gui/my_listbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ void MyListBox::additem(char *texx) {

int MyListBox::processmessage(int mcode, int wParam, NumberPtr lParam) {
if (mcode == CLB_ADDITEM) {
additem((char *)lParam._ptr);
additem((char *)lParam.ptr());
} else if (mcode == CLB_CLEAR)
clearlist();
else if (mcode == CLB_GETCURSEL)
Expand All @@ -146,12 +146,12 @@ int MyListBox::processmessage(int mcode, int wParam, NumberPtr lParam) {
if (topitem + numonscreen <= selected)
topitem = (selected + 1) - numonscreen;
} else if (mcode == CLB_GETTEXT)
Common::strcpy_s((char *)lParam._ptr, 260, itemnames[wParam]);
Common::strcpy_s((char *)lParam.ptr(), 260, itemnames[wParam]);
else if (mcode == CLB_SETTEXT) {
if (wParam < items)
free(itemnames[wParam]);

char *newstri = (char *)lParam._ptr;
char *newstri = (char *)lParam.ptr();
size_t ln = strlen(newstri) + 2;
itemnames[wParam] = (char *)malloc(ln);
Common::strcpy_s(itemnames[wParam], ln, newstri);
Expand Down
4 changes: 2 additions & 2 deletions engines/ags/engine/gui/my_textbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ int MyTextBox::pressedon(int /*mx*/, int /*my*/) {
int MyTextBox::processmessage(int mcode, int wParam, NumberPtr lParam) {

if (mcode == CTB_SETTEXT) {
snprintf(text, sizeof(text), "%s", (const char *)lParam._ptr);
snprintf(text, sizeof(text), "%s", (const char *)lParam.ptr());
needredraw = 1;
} else if (mcode == CTB_GETTEXT)
Common::strcpy_s((char *)lParam._ptr, 260, text); // FIXME! dangerous
Common::strcpy_s((char *)lParam.ptr(), 260, text); // FIXME! dangerous
else if (mcode == CTB_KEYPRESS) {
// NOTE: this deprecated control does not support UTF-8
int key = wParam;
Expand Down
4 changes: 2 additions & 2 deletions engines/ags/engine/script/cc_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1221,8 +1221,8 @@ int ccInstance::Run(int32_t curpc) {
// call only supports a 32-bit value. This is fine in most cases, since
// methods mostly set the ptr on GlobalReturnValue, so it doesn't reach here.
// But just in case, throw a wobbly if it reaches here with a 64-bit pointer
if (fnResult._ptr > reinterpret_cast<void *>(static_cast<uintptr>(0xffffffffu)))
error("Uhandled 64-bit pointer result from plugin method call");
if (fnResult.full() > static_cast<intptr_t>(0xffffffffu))
error("Unhandled 64-bit pointer result from plugin method call");

return_value.SetPluginArgument(fnResult);
}
Expand Down
25 changes: 13 additions & 12 deletions engines/ags/shared/core/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,28 +105,29 @@ enum {
};

/**
* Basic union that can be either a number or a pointer. Helps avoid some
* Basic class that can hold either a number or a pointer. Helps avoid some
* of the more nasty casts the codebase does, which was causing issues
* on 64-bit systems
*/
union NumberPtr {
int32 _value;
void *_ptr;
const void *_constPtr;
class NumberPtr {
intptr_t _value;

NumberPtr() : _ptr(nullptr) {
public:
NumberPtr() : _value(0) {
}
NumberPtr(int value) {
_ptr = nullptr;
NumberPtr(int32_t value) {
_value = value;
}
NumberPtr(void *ptr) : _ptr(ptr) {
NumberPtr(void *ptr) : _value((intptr_t)ptr) {
}
NumberPtr(const void *ptr) : _constPtr(ptr) {
NumberPtr(const void *ptr) : _value((intptr_t)ptr) {
}
operator int() const {
return _value;
operator int32_t() const {
return (int32_t)_value;
}
intptr_t full() const { return _value; }
void *ptr() const { return (void *)_value; }
const void *cptr() const { return (const void *)_value; }
};

} // namespace AGS3
Expand Down

0 comments on commit 25cbcf1

Please sign in to comment.