LWJGL/lwjgl3

[LibFFI] `nffi_prep_cif_var` Missing `safe` Method Calls

gudenau opened this issue · 2 comments

Version

3.3.3

Platform

Linux x64, Linux arm64, Linux arm32, macOS x64, macOS arm64, Windows x64, Windows x86, Windows arm64

JDK

openjdk 22-ea 2024-03-19

Module

LibFFI

Bug description

ffi_prep_cif_var doesn't use the null safe methods to access the arguments like the related ffi_prep_cif does. While uncommon, it is possible to call a var-arg function and pass no args to it. In order to create a FFICIF that takes no args you pass in a null for the PointerBuffer argument.

Currently it is

    @NativeType("ffi_status")
    public static int ffi_prep_cif_var(@NativeType("ffi_cif *") FFICIF cif, @NativeType("ffi_abi") int abi, @NativeType("unsigned int") int nfixedargs, @NativeType("ffi_type *") FFIType rtype, @NativeType("ffi_type **") PointerBuffer atypes) {
        return nffi_prep_cif_var(cif.address(), abi, nfixedargs, atypes.remaining(), rtype.address(), memAddress(atypes));
    }

when it should probably match ffi_prep_cif and be

    @NativeType("ffi_status")
    public static int ffi_prep_cif_var(@NativeType("ffi_cif *") FFICIF cif, @NativeType("ffi_abi") int abi, @NativeType("unsigned int") int nfixedargs, @NativeType("ffi_type *") FFIType rtype, @NativeType("ffi_type **") PointerBuffer atypes) {
        return nffi_prep_cif_var(cif.address(), abi, nfixedargs, remainingSafe(atypes.), rtype.address(), memAddressSafe(atypes));
    }

Stacktrace or crash log output

No response

Variadic functions in C require at least one fixed argument. Calling nffi_prep_cif_var with zero arguments might happen to work on your system, but it is not guaranteed behavior across platforms.

When the official documentation of a function does not specify buffer lengths or if they are nullable or not, I examine the implementation to derive it. I may get it wrong sometimes, but I don't think this is such a case. Both ffi_prep_cif and ffi_prep_cif_var call an internal libffi function with this comment:

/* For non variadic functions isvariadic should be 0 and
   nfixedargs==ntotalargs.

   For variadic calls, isvariadic should be 1 and nfixedargs
   and ntotalargs set as appropriate. nfixedargs must always be >=1 */

and these asserts:

FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
FFI_ASSERT(nfixedargs <= ntotalargs);

Woops, my bad. I was under the impression that varidic stuff could have 0 args.