diff --git a/backport-Add-the-ABI_ATTR-attribute-to-called-functions-891-8.patch b/backport-Add-the-ABI_ATTR-attribute-to-called-functions-891-8.patch new file mode 100644 index 0000000000000000000000000000000000000000..97c92698a5b993b47c8fc916e9caf3a3915aaa04 --- /dev/null +++ b/backport-Add-the-ABI_ATTR-attribute-to-called-functions-891-8.patch @@ -0,0 +1,43 @@ +From bb1a84ed9772ee65e00762dab1c4ae50100d5a27 Mon Sep 17 00:00:00 2001 +From: mikulas-patocka <94898783+mikulas-patocka@users.noreply.github.com> +Date: Sun, 30 Mar 2025 12:07:59 +0200 +Subject: [PATCH] Add the "ABI_ATTR" attribute to called functions (#891) + (#892) + +I accidentally omitted the "ABI_ATTR" attribute, so that the testsuite +fails when testing the Microsoft ABI. + +Fixes: fe203ffbb2bd ("Fix bugs in the x86-64 and x32 target (#887) (#889)") + +Signed-off-by: Mikulas Patocka +--- + testsuite/libffi.call/overread.c | 2 +- + testsuite/libffi.call/x32.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/testsuite/libffi.call/overread.c b/testsuite/libffi.call/overread.c +index d9ae579bc..5ba10774c 100644 +--- a/testsuite/libffi.call/overread.c ++++ b/testsuite/libffi.call/overread.c +@@ -12,7 +12,7 @@ + #include + #include + +-static int fn(unsigned char a, unsigned short b, unsigned int c, unsigned long d) ++static int ABI_ATTR fn(unsigned char a, unsigned short b, unsigned int c, unsigned long d) + { + return (int)(a + b + c + d); + } +diff --git a/testsuite/libffi.call/x32.c b/testsuite/libffi.call/x32.c +index f9ad82de9..9c380a529 100644 +--- a/testsuite/libffi.call/x32.c ++++ b/testsuite/libffi.call/x32.c +@@ -8,7 +8,7 @@ + + #include "ffitest.h" + +-static int fn(int *a) ++static int ABI_ATTR fn(int *a) + { + if (a) + return *a; diff --git a/backport-Fix-bugs-in-the-x86-64-and-x32-target-887-889.patch b/backport-Fix-bugs-in-the-x86-64-and-x32-target-887-889.patch new file mode 100644 index 0000000000000000000000000000000000000000..76a55595195e5b735b2ebda4991e636587f1b7df --- /dev/null +++ b/backport-Fix-bugs-in-the-x86-64-and-x32-target-887-889.patch @@ -0,0 +1,158 @@ +From fe203ffbb2bd7f93a86013d341aa767a406150bc Mon Sep 17 00:00:00 2001 +From: mikulas-patocka <94898783+mikulas-patocka@users.noreply.github.com> +Date: Thu, 27 Mar 2025 01:31:49 +0100 +Subject: [PATCH] Fix bugs in the x86-64 and x32 target (#887) (#889) + +This commit fixes two bugs in ffi in the x86-64 target. The bugs were +introduced by the commit d21881f55ed4a44d464c9091871e69b0bb47611a ("Fix +x86/ffi64 calls with 6 gp and some sse registers"). + +The first bug is that when we pass an argument with less than 8 bytes, +ffi will read memory beyond argument end, causing a crash if the argument +is located just before the end of the mapped region. + +The second bug is in the x32 ABI - pointers in x32 are 4-byte, but GCC +assumes that the pointer values in the registers are zero-extended. ffi +doesn't respect this assumption, causing crashes in the called library. + +For example, when we compile this function for x32: +int fn(int *a) +{ + if (a) + return *a; + return -1; +} +we get this code: +fn: + testq %rdi, %rdi + je .L3 + movl (%edi), %eax + ret +.L3: + movl $-1, %eax + ret +When we call this function using ffi with the argument NULL, the function +crashes because top 4 bytes of the RDI register are not cleared. + + +Fixes: d21881f55ed4 ("Fix x86/ffi64 calls with 6 gp and some sse registers (#848)") + +Signed-off-by: Mikulas Patocka +--- + src/x86/ffi64.c | 2 +- + testsuite/libffi.call/overread.c | 54 ++++++++++++++++++++++++++++++++ + testsuite/libffi.call/x32.c | 31 ++++++++++++++++++ + 3 files changed, 86 insertions(+), 1 deletion(-) + create mode 100644 testsuite/libffi.call/overread.c + create mode 100644 testsuite/libffi.call/x32.c + +diff --git a/src/x86/ffi64.c b/src/x86/ffi64.c +index 982b144cb..1d1b88e04 100644 +--- a/src/x86/ffi64.c ++++ b/src/x86/ffi64.c +@@ -654,7 +654,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, + break; + default: + reg_args->gpr[gprcount] = 0; +- memcpy (®_args->gpr[gprcount], a, sizeof(UINT64)); ++ memcpy (®_args->gpr[gprcount], a, size <= 8 ? size : 8); + } + gprcount++; + break; +diff --git a/testsuite/libffi.call/overread.c b/testsuite/libffi.call/overread.c +new file mode 100644 +index 000000000..d9ae579bc +--- /dev/null ++++ b/testsuite/libffi.call/overread.c +@@ -0,0 +1,54 @@ ++/* Area: ffi_call ++ Purpose: Tests if ffi_call reads data beyond end. ++ Limitations: needs mmap. ++ PR: 887 ++ Originator: Mikulas Patocka */ ++ ++/* { dg-do run } */ ++ ++#include "ffitest.h" ++ ++#ifdef __linux__ ++#include ++#include ++ ++static int fn(unsigned char a, unsigned short b, unsigned int c, unsigned long d) ++{ ++ return (int)(a + b + c + d); ++} ++#endif ++ ++int main(void) ++{ ++#ifdef __linux__ ++ ffi_cif cif; ++ ffi_type *args[MAX_ARGS]; ++ void *values[MAX_ARGS]; ++ ffi_arg rint; ++ char *m; ++ int ps; ++ args[0] = &ffi_type_uchar; ++ args[1] = &ffi_type_ushort; ++ args[2] = &ffi_type_uint; ++ args[3] = &ffi_type_ulong; ++ CHECK(ffi_prep_cif(&cif, ABI_NUM, 4, &ffi_type_sint, args) == FFI_OK); ++ ps = getpagesize(); ++ m = mmap(NULL, ps * 3, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ CHECK(m != MAP_FAILED); ++ CHECK(mprotect(m, ps, PROT_NONE) == 0); ++ CHECK(mprotect(m + ps * 2, ps, PROT_NONE) == 0); ++ values[0] = m + ps * 2 - sizeof(unsigned char); ++ values[1] = m + ps * 2 - sizeof(unsigned short); ++ values[2] = m + ps * 2 - sizeof(unsigned int); ++ values[3] = m + ps * 2 - sizeof(unsigned long); ++ ffi_call(&cif, FFI_FN(fn), &rint, values); ++ CHECK((int)rint == 0); ++ values[0] = m + ps; ++ values[1] = m + ps; ++ values[2] = m + ps; ++ values[3] = m + ps; ++ ffi_call(&cif, FFI_FN(fn), &rint, values); ++ CHECK((int)rint == 0); ++#endif ++ exit(0); ++} +diff --git a/testsuite/libffi.call/x32.c b/testsuite/libffi.call/x32.c +new file mode 100644 +index 000000000..f9ad82de9 +--- /dev/null ++++ b/testsuite/libffi.call/x32.c +@@ -0,0 +1,31 @@ ++/* Area: ffi_call ++ Purpose: Check zero-extension of pointers on x32. ++ Limitations: none. ++ PR: 887 ++ Originator: Mikulas Patocka */ ++ ++/* { dg-do run } */ ++ ++#include "ffitest.h" ++ ++static int fn(int *a) ++{ ++ if (a) ++ return *a; ++ return -1; ++} ++ ++int main(void) ++{ ++ ffi_cif cif; ++ ffi_type *args[MAX_ARGS]; ++ void *values[MAX_ARGS]; ++ void *z[2] = { (void *)0, (void *)1 }; ++ ffi_arg rint; ++ args[0] = &ffi_type_pointer; ++ values[0] = z; ++ CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ffi_type_sint, args) == FFI_OK); ++ ffi_call(&cif, FFI_FN(fn), &rint, values); ++ CHECK((int)rint == -1); ++ exit(0); ++} diff --git a/libffi.spec b/libffi.spec index 7d163e2a6d063526608e050aaac4de8f85f235fa..e73d2eaa9513da6ca91e063028f6f21d3827c431 100644 --- a/libffi.spec +++ b/libffi.spec @@ -1,6 +1,6 @@ Name: libffi Version: 3.4.4 -Release: 5 +Release: 6 Summary: A Portable Foreign Function Interface Library License: MIT URL: http://sourceware.org/libffi @@ -14,6 +14,8 @@ Patch2: backport-fix-x86-ffi64-calls-with-6-gp-and-some-sse-registers.patch Patch3: backport-Robustify-floating-point-comparison-in-test.patch Patch4: backport-Fix-floating-point-compare.patch Patch5: libffi-Add-sw64-architecture.patch +Patch6: backport-Fix-bugs-in-the-x86-64-and-x32-target-887-889.patch +Patch7: backport-Add-the-ABI_ATTR-attribute-to-called-functions-891-8.patch BuildRequires: gcc gcc-c++ dejagnu BuildRequires: make @@ -101,6 +103,9 @@ fi %{_infodir}/libffi.info.gz %changelog +* Tue Jul 29 2025 yanglongkang - 3.4.4-6 +- fix bugs in the x86-64 and x32 target + * Tue Jul 29 2025 yanglongkang - 3.4.4-5 - Fix x86/ffi64 calls with 6 gp and some sse registers Robustify floating point comparison in test