From 8e07e68429ce52e8478b930d438e51d550d6e1a9 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Sat, 6 Sep 2025 15:05:56 +0200 Subject: [PATCH] Set ErlNifEntry.min_erts to a placeholder value This value was introduced with NIF version 2.14 (so, OTP-21, erts-10.0). Us leaving it unassigned and defaulting to NIF version 2.15 means the OTP is currently always putting a random pointer into the respective field here: https://github.com/erlang/otp/blob/ae81b2f6ff2d541c01242f12cdbd5238aa4b26bd/erts/emulator/beam/erl_nif.c#L4581-L4585 It is used if one tries to load a NIF library that was compiled for a newer NIF version to display a debug message, at which point it would perform an out-of-bounds read. As we currently default to NIF v2.15 (OTP-22) and only have features up to 2.16 (OTP-24), there are probably very few cases of this actually occurring in the wild. --- rustler/src/codegen_runtime.rs | 12 ++++++++++++ rustler/src/sys/types.rs | 1 + rustler_codegen/src/init.rs | 1 + 3 files changed, 14 insertions(+) diff --git a/rustler/src/codegen_runtime.rs b/rustler/src/codegen_runtime.rs index 9f0ef120..9ab1f898 100644 --- a/rustler/src/codegen_runtime.rs +++ b/rustler/src/codegen_runtime.rs @@ -140,3 +140,15 @@ where } } } + +pub const fn min_erts() -> &'static [u8] { + if cfg!(feature = "nif_version_2_17") { + b"OTP-26.0\0" + } else if cfg!(feature = "nif_version_2_16") { + b"OTP-24.0\0" + } else if cfg!(feature = "nif_version_2_15") { + b"OTP-22.0\0" + } else { + b"OTP-21.0\0" + } +} diff --git a/rustler/src/sys/types.rs b/rustler/src/sys/types.rs index 09db65f9..24f1aab0 100644 --- a/rustler/src/sys/types.rs +++ b/rustler/src/sys/types.rs @@ -85,6 +85,7 @@ pub struct ErlNifEntry { pub vm_variant: *const c_char, pub options: c_uint, // added in 2.7 pub sizeof_ErlNifResourceTypeInit: usize, // added in 2.12 + pub min_erts: *const c_char, // added in 2.14 } pub const ERL_NIF_DIRTY_NIF_OPTION: c_uint = 1; diff --git a/rustler_codegen/src/init.rs b/rustler_codegen/src/init.rs index 61857e11..87b6d666 100644 --- a/rustler_codegen/src/init.rs +++ b/rustler_codegen/src/init.rs @@ -125,6 +125,7 @@ impl From for proc_macro2::TokenStream { vm_variant: b"beam.vanilla\0".as_ptr() as *const rustler::codegen_runtime::c_char, options: 0, sizeof_ErlNifResourceTypeInit: rustler::codegen_runtime::get_nif_resource_type_init_size(), + min_erts: rustler::codegen_runtime::min_erts().as_ptr() as *const rustler::codegen_runtime::c_char, }; unsafe {