From 6bef09f68b81290a69b7a6efb7252bde86669d9e Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 20 Dec 2024 18:00:25 +0100 Subject: [PATCH] fix(core): work around alignment problem when using Emscripten The data we read from the KMX file is not in places 32-bit aligned, e.g. `dpGroupArray` will often start at a 16-bit boundary. Emscripten doesn't like this and will abort the program if `SAFE_HEAP=1` is defined. This change works around the problem by calling `CopyKeyboard` and thus expanding the structure. See #12844. --- core/src/kmx/kmx_file.cpp | 18 ++++++++++-------- core/src/kmx/kmx_processevent.h | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/core/src/kmx/kmx_file.cpp b/core/src/kmx/kmx_file.cpp index 2eea0185813..9a4100c754d 100644 --- a/core/src/kmx/kmx_file.cpp +++ b/core/src/kmx/kmx_file.cpp @@ -68,11 +68,11 @@ KMX_BOOL KMX_ProcessEvent::LoadKeyboardFromBlob( *lpKeyboard = NULL; -#ifdef KMX_64BIT +#if defined(KMX_64BIT) || defined(__EMSCRIPTEN__) // allocate enough memory for expanded data structure + original data. - // Expanded data structure is double the size of data on disk (8-byte - // pointers) - on disk the "pointers" are relative to the beginning of - // the file. + // Expanded data structure is no more than double the size of data on + // disk (8-byte pointers) - on disk the "pointers" are relative to the + // beginning of the file. // We save the original data at the end of buf; we don't copy strings, so // those will remain in the location at the end of the buffer. buf = new KMX_BYTE[sz * 3]; @@ -84,7 +84,7 @@ KMX_BOOL KMX_ProcessEvent::LoadKeyboardFromBlob( DebugLog("Not allocmem"); return FALSE; } -#ifdef KMX_64BIT +#if defined(KMX_64BIT) || defined(__EMSCRIPTEN__) filebase = buf + sz * 2; #else filebase = buf; @@ -103,7 +103,7 @@ KMX_BOOL KMX_ProcessEvent::LoadKeyboardFromBlob( return FALSE; } -#ifdef KMX_64BIT +#if defined(KMX_64BIT) || defined(__EMSCRIPTEN__) kbp = CopyKeyboard(buf, filebase); #else kbp = FixupKeyboard(buf, filebase); @@ -132,13 +132,15 @@ PKMX_WCHAR KMX_ProcessEvent::StringOffset(PKMX_BYTE base, KMX_DWORD offset) return (PKMX_WCHAR)(base + offset); } -#ifdef KMX_64BIT +#if defined(KMX_64BIT) || defined(__EMSCRIPTEN__) /** CopyKeyboard will copy the data read into bufp from x86-sized structures into x64-sized structures starting at `base` * After this function finishes, we still need to keep the original data because we don't copy the strings - This method is used on 64-bit architectures. + This method is used on 64-bit architectures as well as with Emscripten. + Emscripten requires 32-bit alignment for pointers which we don't always + have in the KMX data (see #12844). */ LPKEYBOARD KMX_ProcessEvent::CopyKeyboard(PKMX_BYTE bufp, PKMX_BYTE base) { diff --git a/core/src/kmx/kmx_processevent.h b/core/src/kmx/kmx_processevent.h index 090488dccb4..202541e4550 100644 --- a/core/src/kmx/kmx_processevent.h +++ b/core/src/kmx/kmx_processevent.h @@ -57,7 +57,7 @@ class KMX_ProcessEvent { KMX_BOOL LoadKeyboardFromBlob(PKMX_BYTE buf, size_t sz, LPKEYBOARD* lpKeyboard); KMX_BOOL VerifyKeyboard(PKMX_BYTE filebase, size_t sz); KMX_BOOL VerifyChecksum(PKMX_BYTE buf, size_t sz); -#ifdef KMX_64BIT +#if defined(KMX_64BIT) || defined(__EMSCRIPTEN__) LPKEYBOARD CopyKeyboard(PKMX_BYTE bufp, PKMX_BYTE base); #else LPKEYBOARD FixupKeyboard(PKMX_BYTE bufp, PKMX_BYTE base);