{"record":{"id":"a77ec72c1b3d5ef1","repo":"wasmerio/wasmer","slug":"failed-to-convert-u64-address-to-m-offset","errorCode":null,"errorMessage":"Failed to convert u64 address to M::Offset","messagePattern":"Failed to convert u64 address to M::Offset","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/wasix/src/syscalls/wasix/dlsym.rs","lineNumber":59,"sourceCode":"        Some(ModuleHandle::from(handle))\n    };\n    let symbol = linker.resolve_export(&mut ctx, handle, &symbol);\n\n    let (env, mut store) = ctx.data_and_store_mut();\n    let memory = unsafe { env.memory_view(&store) };\n\n    let symbol = wasi_try_dl!(\n        symbol,\n        \"failed to resolve symbol: {}\",\n        memory,\n        err_buf,\n        err_buf_len\n    );\n\n    match symbol {\n        ResolvedExport::Function { func_ptr: addr } | ResolvedExport::Global { data_ptr: addr } => {\n            let Ok(addr) = addr.try_into() else {\n                panic!(\"Failed to convert u64 address to M::Offset\");\n            };\n            wasi_try_mem_ok!(out_symbol.write(&memory, addr));\n        }\n    }\n\n    Ok(Errno::Success)\n}\n","sourceCodeStart":41,"sourceCodeEnd":67,"githubUrl":"https://github.com/wasmerio/wasmer/blob/8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5/lib/wasix/src/syscalls/wasix/dlsym.rs#L41-L67","documentation":"The dlsym syscall resolves a symbol to a 64-bit address (function pointer or global data pointer) and writes it out to guest memory. The address must fit in the memory's Offset type (u32 for memory32); if a u64 address exceeds it, dlsym panics with \"Failed to convert u64 address to M::Offset\".","triggerScenarios":"Calling dlsym on a module whose resolved export function pointer or global data address exceeds 4GiB while running with a 32-bit memory (M = Memory32).","commonSituations":"dlopen'ing a module compiled for 64-bit memories (memory64) into a 32-bit-memory instance and then looking up its symbols; oversized/incorrect pointer values returned by a broken resolver.","solutions":["Ensure the loaded module and the calling instance both use matching memory index types (32-bit or 64-bit).","Recompile the shared module with a 32-bit memory if the host instance uses memory32.","If you maintain the runtime, write the full u64 into an i64 out-parameter or return Errno::Overflow instead of panicking.","Verify the resolved address via the module's exports before calling dlsym on suspicious symbols."],"exampleFix":"// before\n(module (memory i64 1)) ;; memory64 module loaded into 32-bit instance\n// after\n(module (memory 1)) ;; 32-bit memory matching the host instance","handlingStrategy":"validation","validationCode":"// Ensure the dlopen'ed module uses the same memory index type as the caller\n// Reject memory64 modules before dlopen:\nfn uses_memory64(module: &wasmer::Module) -> bool {\n    module.imports().filter(|i| i.ty().memory().map(|m| m.index_type()) == Some(wasmer::IndexType::I64)).count() > 0\n}","typeGuard":"fn fits_in_memory32(addr: u64) -> bool { addr <= u32::MAX as u64 }","tryCatchPattern":null,"preventionTips":["Match memory index types (i32 vs i64) between the host instance and all dynamically loaded modules.","Compile shared libraries with 32-bit memories when the main module uses memory32.","Prefer a 64-bit memory instance if you expect addresses above 4GiB.","Validate resolved addresses before writing them to 32-bit out-pointers."],"tags":["wasix","panic","dlsym","memory64","address-space"],"backgroundTag":"address-out-of-range","analyzedSha":"8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5","analyzedAt":"2026-09-01T23:06:31.009Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}