LibJS: Fix pointer authentication failure in TypedArray#5116
LibJS: Fix pointer authentication failure in TypedArray#5116ADKaster merged 1 commit intoLadybirdBrowser:masterfrom
TypedArray#5116Conversation
`TypedArray` objects need to know their own constructor objects to allow copying. This was implemented by storing a function pointer to the `Intrinsic` object's method which returns the constructor object. The problem is that function pointers aren't polymorphic, we can't legally just cast e.g. a `Derived* (*ptr)(void)` to `Base* (*ptr)(void)` (this is why the code needed a `bit_cast` to even compile). But this wasn't actually a problem in practice because their ABIs were the same. But with pointer authentication (Apple's `arm64e` ABI) this signature mismatch becomes a hard failure and crashes the process. Fix this by adding a virtual function that returns the intrinsic constructor (actually, a `NativeFunction`, as typed arrays constructors don't inherit from the base `TypedArray` constructor) instead of the function pointer. With this, test-js passes and Ladybird launches correctly when built (with a lot of vcpkg hacks) for arm64e.
|
Public arm64e support is only available with the beta releases of Xcode 26 and macOS Tahoe. #!/opt/homebrew/bin/bash
rewritten_args=()
skip_next=0
args=("$@")
found=0
for ((i = 0; i < $#; i++)); do
if [[ $skip_next -eq 1 ]]; then
skip_next=0
continue
fi
arg="${args[i]}"
if [[ "$arg" == "-arch" && $((i + 1)) -lt $# && "${args[i + 1]}" == "arm64" ]]; then
rewritten_args+=("-arch" "arm64e")
skip_next=1
found=1
elif [[ "$arg" == --target=arm64-* ]]; then
new_arg="${arg/--target=arm64-/--target=arm64e-}"
rewritten_args+=("$new_arg")
found=1
elif [[ "$arg" == "-target" && $((i + 1)) -lt $# && "${args[i + 1]}" == arm64-* ]]; then
new_target="${args[i + 1]/arm64-/arm64e-}"
rewritten_args+=("-target" "$new_target")
skip_next=1
found=1
else
rewritten_args+=("$arg")
fi
done
if [ "$found" -eq 0 ]; then
rewritten_args+=("-arch" "arm64e")
fi
exec $(xcrun -f clang++) "${rewritten_args[@]}"We also need the hack to vcpkg's meson integration script for Xcode 26 compat: --- ./buildtrees/versioning_/versions/vcpkg-tool-meson/f0eaf59cb8c65aaf2fa2c1ea4a5ab75a5c04d727/vcpkg_configure_meson.cmake 2025-06-11 08:28:55
+++ ./packages/vcpkg-tool-meson_arm64-osx-dynamic/share/vcpkg-tool-meson/vcpkg_configure_meson.cmake 2025-06-15 13:31:17
@@ -324,9 +324,9 @@
vcpkg_cmake_get_vars(cmake_vars_file)
debug_message("Including cmake vars from: ${cmake_vars_file}")
include("${cmake_vars_file}")
- vcpkg_list(APPEND arg_OPTIONS --backend ninja --wrap-mode nodownload -Doptimization=plain)
+ vcpkg_list(APPEND arg_OPTIONS --backend ninja --wrap-mode nodownload -Dbuildtype=plain -Db_ndebug=if-release)
z_vcpkg_get_build_and_host_system(MESON_HOST_MACHINE MESON_BUILD_MACHINE IS_CROSS)
if(arg_CONFIG STREQUAL "DEBUG")
|
|
Regarding that meson hack, can we not patch meson's sources in vcpkg? Or do they not pull meson from source. If you don't want to, I can take a look. It's already been a week since 1.8.2, so I'm not sure when they intend to release the next bump, and the patch file for mesonbuild/meson#14548 is pretty small. |
|
Can the contents of that build script not be replicated by messing with a vcpkg triplet file? We have our own triplets as it is. Is there a tracking issue for arm64e in vcpkg? Is this a CMake limitation as well? I remember seeing a CMake issue from Evan on the Swift team about how CMake and mixed arm64e/arm64 targets are not friends. Something about wanting to pull the triple information from CMAKE_OSX_DEPLOYMENT_TARGET. |
ADKaster
left a comment
There was a problem hiding this comment.
No problem with the changes themselves.
I have very limited free time for 2 more weeks, so I'd love if you could get that patch into vcpkg. re. enabling arm64e in vcpkg, what do you think after our brief convo on the MSVC STL Discord server? |
|
I think that enabling arm64e in vcpkg won't be 'hard' per se, just a bit of busywork. It would definitely be a good idea to use that abi for release/distribution builds. Assuming lldb and the sanitizers can handle it. |
TypedArrayobjects need to know their own constructor objects to allow copying. This was implemented by storing a function pointer to theIntrinsicobject's method which returns the constructor object.The problem is that function pointers aren't polymorphic, we can't legally just cast e.g. a
Derived* (*ptr)(void)toBase* (*ptr)(void)(this is why the code needed abit_castto even compile). But this wasn't actually a problem in practice because their ABIs were the same. But with pointer authentication (Apple'sarm64eABI) this signature mismatch becomes a hard failure and crashes the process.Fix this by adding a virtual function that returns the intrinsic constructor (actually, a
NativeFunction, as typed arrays constructors don't inherit from the baseTypedArrayconstructor) instead of the function pointer.With this, test-js passes and Ladybird launches correctly when built (with a lot of vcpkg hacks) for arm64e.