diff --git a/src/x86/ffi64.c b/src/x86/ffi64.c index 982b144c..1d1b88e0 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 00000000..d9ae579b --- /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 00000000..f9ad82de --- /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); +}