Bug #680. Don't accept floats or small ints as var args. (#628)
authorAnthony Green <green@moxielogic.com>
Tue, 23 Mar 2021 15:31:08 +0000 (11:31 -0400)
committerGitHub <noreply@github.com>
Tue, 23 Mar 2021 15:31:08 +0000 (11:31 -0400)
* Bug #680.  Don't accept floats or small ints as var args.

* Bug #680.  Don't accept floats or small ints as var args.

* Bug #680.  Don't accept floats or small ints as var args.

README.md
doc/libffi.texi
include/ffi.h.in
src/prep_cif.c
testsuite/libffi.call/va_1.c
testsuite/libffi.call/va_2.c [new file with mode: 0644]
testsuite/libffi.closures/cls_uchar_va.c [deleted file]
testsuite/libffi.closures/cls_ushort_va.c [deleted file]

index 4225d85345828e7e879d2f2fae043db972d4fd55..23b10ce5c34a1610e1c38f2856d90a30ac390ba7 100644 (file)
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ bridge from the interpreter program to compiled code.
 The libffi library provides a portable, high level programming
 interface to various calling conventions. This allows a programmer to
 call any function specified by a call interface description at run
-time.  
+time.
 
 FFI stands for Foreign Function Interface.  A foreign function
 interface is the popular name for the interface that allows code
@@ -137,15 +137,15 @@ install autoconf, automake and libtool.
 
 You may want to tell configure where to install the libffi library and
 header files. To do that, use the ``--prefix`` configure switch.  Libffi
-will install under /usr/local by default. 
+will install under /usr/local by default.
 
 If you want to enable extra run-time debugging checks use the the
 ``--enable-debug`` configure switch. This is useful when your program dies
-mysteriously while using libffi. 
+mysteriously while using libffi.
 
 Another useful configure switch is ``--enable-purify-safety``. Using this
 will add some extra code which will suppress certain warnings when you
-are using Purify with libffi. Only use this switch when using 
+are using Purify with libffi. Only use this switch when using
 Purify, as it will slow down the library.
 
 If you don't want to build documentation, use the ``--disable-docs``
@@ -164,7 +164,7 @@ For 64-bit Windows builds, use ``CC="path/to/msvcc.sh -m64"`` and
 It is also possible to build libffi on Windows platforms with the LLVM
 project's clang-cl compiler, like below:
 
-    path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP" 
+    path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP"
 
 When building with MSVC under a MingW environment, you may need to
 remove the line in configure that sets 'fix_srcfile_path' to a 'cygpath'
@@ -199,11 +199,14 @@ History
 See the git log for details at http://github.com/libffi/libffi.
 
     3.4 TBD
+        Add static trampoline support for Linux on x86_64 and ARM64.
        Add support for Alibaba's CSKY architecture.
         Add support for Intel Control-flow Enforcement Technology (CET).
-       Add support for ARM Pointer Authentication (PA).
-       Fix 32-bit PPC regression.
-       Fix MIPS soft-float problem.
+        Add support for ARM Pointer Authentication (PA).
+        Fix 32-bit PPC regression.
+        Fix MIPS soft-float problem.
+        Reject float and small integer argument in ffi_prep_cif_var().
+          Callers must promote these types themselves.
 
     3.3 Nov-23-19
         Add RISC-V support.
@@ -216,10 +219,10 @@ See the git log for details at http://github.com/libffi/libffi.
         Raw java (gcj) API deprecated.
         Add pre-built PDF documentation to source distribution.
         Many new test cases and bug fixes.
-        
+
     3.2.1 Nov-12-14
         Build fix for non-iOS AArch64 targets.
-    
+
     3.2 Nov-11-14
         Add C99 Complex Type support (currently only supported on
           s390).
@@ -227,7 +230,7 @@ See the git log for details at http://github.com/libffi/libffi.
           Windows/Linux.
         Add OpenRISC and Cygwin-64 support.
         Bug fixes.
-    
+
     3.1 May-19-14
         Add AArch64 (ARM64) iOS support.
         Add Nios II support.
@@ -240,7 +243,7 @@ See the git log for details at http://github.com/libffi/libffi.
           failures, and respect the $CC and $CXX environment variables.
         Archive off the manually maintained ChangeLog in favor of git
           log.
-    
+
     3.0.13 Mar-17-13
         Add Meta support.
         Add missing Moxie bits.
@@ -250,7 +253,7 @@ See the git log for details at http://github.com/libffi/libffi.
         Fix the install dir location for some platforms when building
           with GCC (OS X, Solaris).
         Fix Cygwin regression.
-    
+
     3.0.12 Feb-11-13
         Add Moxie support.
         Add AArch64 support.
@@ -262,7 +265,7 @@ See the git log for details at http://github.com/libffi/libffi.
         Add support for native vendor compilers on
           Solaris and AIX.
         Work around LLVM/GCC interoperability issue on x86_64.
-    
+
     3.0.11 Apr-11-12
         Lots of build fixes.
         Add support for variadic functions (ffi_prep_cif_var).
@@ -273,7 +276,7 @@ See the git log for details at http://github.com/libffi/libffi.
         Integration with iOS' xcode build tools.
         Fix Octeon and MC68881 support.
         Fix code pessimizations.
-    
+
     3.0.10 Aug-23-11
         Add support for Apple's iOS.
         Add support for ARM VFP ABI.
@@ -287,128 +290,128 @@ See the git log for details at http://github.com/libffi/libffi.
           Solaris compiler.
         Testsuite fixes for Tru64 Unix.
         Additional platform support.
-    
+
     3.0.9 Dec-31-09
         Add AVR32 and win64 ports.  Add ARM softfp support.
         Many fixes for AIX, Solaris, HP-UX, *BSD.
         Several PowerPC and x86-64 bug fixes.
         Build DLL for windows.
-    
+
     3.0.8 Dec-19-08
         Add *BSD, BeOS, and PA-Linux support.
-    
+
     3.0.7 Nov-11-08
         Fix for ppc FreeBSD.
         (thanks to Andreas Tobler)
-    
+
     3.0.6 Jul-17-08
         Fix for closures on sh.
         Mark the sh/sh64 stack as non-executable.
         (both thanks to Kaz Kojima)
-    
+
     3.0.5 Apr-3-08
         Fix libffi.pc file.
         Fix #define ARM for IcedTea users.
         Fix x86 closure bug.
-    
+
     3.0.4 Feb-24-08
         Fix x86 OpenBSD configury.
-    
+
     3.0.3 Feb-22-08
         Enable x86 OpenBSD thanks to Thomas Heller, and
           x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
         Clean up test instruction in README.
-    
+
     3.0.2 Feb-21-08
         Improved x86 FreeBSD support.
         Thanks to Björn König.
-    
+
     3.0.1 Feb-15-08
         Fix instruction cache flushing bug on MIPS.
         Thanks to David Daney.
-    
+
     3.0.0 Feb-15-08
         Many changes, mostly thanks to the GCC project.
         Cygnus Solutions is now Red Hat.
-    
+
       [10 years go by...]
-    
+
     1.20 Oct-5-98
         Raffaele Sena produces ARM port.
-    
+
     1.19 Oct-5-98
         Fixed x86 long double and long long return support.
         m68k bug fixes from Andreas Schwab.
         Patch for DU assembler compatibility for the Alpha from Richard
           Henderson.
-    
+
     1.18 Apr-17-98
         Bug fixes and MIPS configuration changes.
-    
+
     1.17 Feb-24-98
         Bug fixes and m68k port from Andreas Schwab. PowerPC port from
         Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
-    
+
     1.16 Feb-11-98
         Richard Henderson produces Alpha port.
-    
+
     1.15 Dec-4-97
         Fixed an n32 ABI bug. New libtool, auto* support.
-    
+
     1.14 May-13-97
         libtool is now used to generate shared and static libraries.
         Fixed a minor portability problem reported by Russ McManus
         <mcmanr@eq.gs.com>.
-    
+
     1.13 Dec-2-96
         Added --enable-purify-safety to keep Purify from complaining
           about certain low level code.
         Sparc fix for calling functions with < 6 args.
         Linux x86 a.out fix.
-    
+
     1.12 Nov-22-96
-        Added missing ffi_type_void, needed for supporting void return 
-          types. Fixed test case for non MIPS machines. Cygnus Support 
-          is now Cygnus Solutions. 
-    
+        Added missing ffi_type_void, needed for supporting void return
+          types. Fixed test case for non MIPS machines. Cygnus Support
+          is now Cygnus Solutions.
+
     1.11 Oct-30-96
         Added notes about GNU make.
-    
+
     1.10 Oct-29-96
         Added configuration fix for non GNU compilers.
-    
+
     1.09 Oct-29-96
-        Added --enable-debug configure switch. Clean-ups based on LCLint 
-        feedback. ffi_mips.h is always installed. Many configuration 
+        Added --enable-debug configure switch. Clean-ups based on LCLint
+        feedback. ffi_mips.h is always installed. Many configuration
         fixes. Fixed ffitest.c for sparc builds.
-    
+
     1.08 Oct-15-96
         Fixed n32 problem. Many clean-ups.
-    
+
     1.07 Oct-14-96
         Gordon Irlam rewrites v8.S again. Bug fixes.
-    
+
     1.06 Oct-14-96
-        Gordon Irlam improved the sparc port. 
-    
+        Gordon Irlam improved the sparc port.
+
     1.05 Oct-14-96
         Interface changes based on feedback.
-    
+
     1.04 Oct-11-96
         Sparc port complete (modulo struct passing bug).
-    
+
     1.03 Oct-10-96
         Passing struct args, and returning struct values works for
         all architectures/calling conventions. Expanded tests.
-    
+
     1.02 Oct-9-96
         Added SGI n32 support. Fixed bugs in both o32 and Linux support.
         Added "make test".
-    
+
     1.01 Oct-8-96
         Fixed float passing bug in mips version. Restructured some
         of the code. Builds cleanly with SGI tools.
-    
+
     1.00 Oct-7-96
         First release. No public announcement.
 
index bd305936c2dd8185e2e076e8fde60686cfecb4f8..79f937733912a2a4f506ae68d0813dfdeb0a0cca 100644 (file)
@@ -18,7 +18,7 @@
 This manual is for libffi, a portable foreign function interface
 library.
 
-Copyright @copyright{} 2008--2019 Anthony Green and Red Hat, Inc.
+Copyright @copyright{} 2008--2019, 2021 Anthony Green and Red Hat, Inc.
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
@@ -176,6 +176,11 @@ variadic arguments.  It must be greater than zero.
 @var{ntotalargs} the total number of arguments, including variadic
 and fixed arguments.  @var{argtypes} must have this many elements.
 
+@code{ffi_prep_cif_var} will return @code{FFI_BAD_ARGTYPE} if any of
+the variable argument types are @code{ffi_type_float} (promote to
+@code{ffi_type_double} first), or any integer type small than an int
+(promote to an int-sized type first).
+
 Note that, different cif's must be prepped for calls to the same
 function when different numbers of arguments are passed.
 
@@ -249,26 +254,26 @@ int main()
   void *values[1];
   char *s;
   ffi_arg rc;
-  
-  /* Initialize the argument info vectors */    
+
+  /* Initialize the argument info vectors */
   args[0] = &ffi_type_pointer;
   values[0] = &s;
-  
+
   /* Initialize the cif */
-  if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
+  if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
                       &ffi_type_sint, args) == FFI_OK)
     @{
       s = "Hello World!";
       ffi_call(&cif, puts, &rc, values);
       /* rc now holds the result of the call to puts */
-      
-      /* values holds a pointer to the function's arg, so to 
-         call puts() again all we need to do is change the 
+
+      /* values holds a pointer to the function's arg, so to
+         call puts() again all we need to do is change the
          value of s */
       s = "This is cool!";
       ffi_call(&cif, puts, &rc, values);
     @}
-  
+
   return 0;
 @}
 @end example
@@ -624,7 +629,7 @@ Here is the corresponding code to describe this struct to
       tm_type.size = tm_type.alignment = 0;
       tm_type.type = FFI_TYPE_STRUCT;
       tm_type.elements = &tm_type_elements;
-    
+
       for (i = 0; i < 9; i++)
           tm_type_elements[i] = &ffi_type_sint;
 
@@ -887,7 +892,7 @@ writable and executable addresses.
 @node Closure Example
 @section Closure Example
 
-A trivial example that creates a new @code{puts} by binding 
+A trivial example that creates a new @code{puts} by binding
 @code{fputs} with @code{stdout}.
 
 @example
index 14ec807d9c938fec61010f627f58bad699742563..d16f307e64bebd72558a094d5df649e3947dd94d 100644 (file)
@@ -1,6 +1,7 @@
 /* -----------------------------------------------------------------*-C-*-
-   libffi @VERSION@ - Copyright (c) 2011, 2014, 2019 Anthony Green
-                    - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
+   libffi @VERSION@
+     - Copyright (c) 2011, 2014, 2019, 2021 Anthony Green
+     - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
 
    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
@@ -217,7 +218,8 @@ FFI_EXTERN ffi_type ffi_type_complex_longdouble;
 typedef enum {
   FFI_OK = 0,
   FFI_BAD_TYPEDEF,
-  FFI_BAD_ABI
+  FFI_BAD_ABI,
+  FFI_BAD_ARGTYPE
 } ffi_status;
 
 typedef struct {
@@ -269,7 +271,7 @@ typedef ffi_raw ffi_java_raw;
 #endif
 
 
-FFI_API 
+FFI_API
 void ffi_raw_call (ffi_cif *cif,
                   void (*fn)(void),
                   void *rvalue,
@@ -374,8 +376,8 @@ typedef struct {
 
 #if !FFI_NATIVE_RAW_API
 
-  /* If this is enabled, then a raw closure has the same layout 
-     as a regular closure.  We use this to install an intermediate 
+  /* If this is enabled, then a raw closure has the same layout
+     as a regular closure.  We use this to install an intermediate
      handler to do the transaltion, void** -> ffi_raw*.  */
 
   void     (*translate_args)(ffi_cif*,void*,void**,void*);
@@ -400,8 +402,8 @@ typedef struct {
 
 #if !FFI_NATIVE_RAW_API
 
-  /* If this is enabled, then a raw closure has the same layout 
-     as a regular closure.  We use this to install an intermediate 
+  /* If this is enabled, then a raw closure has the same layout
+     as a regular closure.  We use this to install an intermediate
      handler to do the translation, void** -> ffi_raw*.  */
 
   void     (*translate_args)(ffi_cif*,void*,void**,void*);
@@ -462,7 +464,7 @@ FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
 
 /* ---- Public interface definition -------------------------------------- */
 
-FFI_API 
+FFI_API
 ffi_status ffi_prep_cif(ffi_cif *cif,
                        ffi_abi abi,
                        unsigned int nargs,
@@ -495,18 +497,18 @@ ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
 #endif
 
 /* If these change, update src/mips/ffitarget.h. */
-#define FFI_TYPE_VOID       0    
+#define FFI_TYPE_VOID       0
 #define FFI_TYPE_INT        1
-#define FFI_TYPE_FLOAT      2    
+#define FFI_TYPE_FLOAT      2
 #define FFI_TYPE_DOUBLE     3
 #if @HAVE_LONG_DOUBLE@
 #define FFI_TYPE_LONGDOUBLE 4
 #else
 #define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
 #endif
-#define FFI_TYPE_UINT8      5   
+#define FFI_TYPE_UINT8      5
 #define FFI_TYPE_SINT8      6
-#define FFI_TYPE_UINT16     7 
+#define FFI_TYPE_UINT16     7
 #define FFI_TYPE_SINT16     8
 #define FFI_TYPE_UINT32     9
 #define FFI_TYPE_SINT32     10
index 1db3804b210d9b0d7f5808d9b0d2555c6b7d6fd8..c1832b10302fa355ecf9d5d2b749946492b88246 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------
-   prep_cif.c - Copyright (c) 2011, 2012  Anthony Green
+   prep_cif.c - Copyright (c) 2011, 2012, 2021  Anthony Green
                 Copyright (c) 1996, 1998, 2007  Red Hat, Inc.
 
    Permission is hereby granted, free of charge, to any person obtaining
@@ -231,7 +231,26 @@ ffi_status ffi_prep_cif_var(ffi_cif *cif,
                             ffi_type *rtype,
                             ffi_type **atypes)
 {
-  return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
+  ffi_status rc;
+  size_t int_size = ffi_type_sint.size;
+  int i;
+
+  rc = ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
+
+  if (rc != FFI_OK)
+    return rc;
+
+  for (i = 1; i < ntotalargs; i++)
+    {
+      ffi_type *arg_type = atypes[i];
+      if (arg_type == &ffi_type_float
+          || ((arg_type->type != FFI_TYPE_STRUCT
+               && arg_type->type != FFI_TYPE_COMPLEX)
+              && arg_type->size < int_size))
+        return FFI_BAD_ARGTYPE;
+    }
+
+  return FFI_OK;
 }
 
 #if FFI_CLOSURES
index 59d085c832adf40e4b5424e922fd7dc2a60862e0..ccc6faf5c932dfe8f018795c7d9478e0c0e60629 100644 (file)
@@ -5,7 +5,6 @@
    Originator:         ARM Ltd. */
 
 /* { dg-do run } */
-/* { dg-output "" { xfail avr32*-*-* m68k-*-* alpha-*-* } } */
 
 #include "ffitest.h"
 #include <stdarg.h>
@@ -25,62 +24,10 @@ struct large_tag
   unsigned e;
 };
 
-static int
-test_fn (int n, ...)
-{
-  va_list ap;
-  struct small_tag s1;
-  struct small_tag s2;
-  struct large_tag l;
-  unsigned char uc;
-  signed char sc;
-  unsigned short us;
-  signed short ss;
-  unsigned int ui;
-  signed int si;
-  unsigned long ul;
-  signed long sl;
-  float f;
-  double d;
-
-  va_start (ap, n);
-  s1 = va_arg (ap, struct small_tag);
-  l = va_arg (ap, struct large_tag);
-  s2 = va_arg (ap, struct small_tag);
-
-  uc = va_arg (ap, unsigned);
-  sc = va_arg (ap, signed);
-
-  us = va_arg (ap, unsigned);
-  ss = va_arg (ap, signed);
-
-  ui = va_arg (ap, unsigned int);
-  si = va_arg (ap, signed int);
-
-  ul = va_arg (ap, unsigned long);
-  sl = va_arg (ap, signed long);
-
-  f = va_arg (ap, double);     /* C standard promotes float->double
-                                  when anonymous */
-  d = va_arg (ap, double);
-
-  printf ("%u %u %u %u %u %u %u %u %u uc=%u sc=%d %u %d %u %d %lu %ld %f %f\n",
-         s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
-         s2.a, s2.b,
-         uc, sc,
-         us, ss,
-         ui, si,
-         ul, sl,
-         f, d);
-  va_end (ap);
-  return n + 1;
-}
-
 int
 main (void)
 {
   ffi_cif cif;
-  void* args[15];
   ffi_type* arg_types[15];
 
   ffi_type s_type;
@@ -89,24 +36,6 @@ main (void)
   ffi_type l_type;
   ffi_type *l_type_elements[6];
 
-  struct small_tag s1;
-  struct small_tag s2;
-  struct large_tag l1;
-
-  int n;
-  ffi_arg res;
-
-  unsigned char uc;
-  signed char sc;
-  unsigned short us;
-  signed short ss;
-  unsigned int ui;
-  signed int si;
-  unsigned long ul;
-  signed long sl;
-  double d1;
-  double f1;
-
   s_type.size = 0;
   s_type.alignment = 0;
   s_type.type = FFI_TYPE_STRUCT;
@@ -144,53 +73,6 @@ main (void)
   arg_types[13] = &ffi_type_double;
   arg_types[14] = NULL;
 
-  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_OK);
-
-  s1.a = 5;
-  s1.b = 6;
-
-  l1.a = 10;
-  l1.b = 11;
-  l1.c = 12;
-  l1.d = 13;
-  l1.e = 14;
-
-  s2.a = 7;
-  s2.b = 8;
-
-  n = 41;
-
-  uc = 9;
-  sc = 10;
-  us = 11;
-  ss = 12;
-  ui = 13;
-  si = 14;
-  ul = 15;
-  sl = 16;
-  f1 = 2.12;
-  d1 = 3.13;
-
-  args[0] = &n;
-  args[1] = &s1;
-  args[2] = &l1;
-  args[3] = &s2;
-  args[4] = &uc;
-  args[5] = &sc;
-  args[6] = &us;
-  args[7] = &ss;
-  args[8] = &ui;
-  args[9] = &si;
-  args[10] = &ul;
-  args[11] = &sl;
-  args[12] = &f1;
-  args[13] = &d1;
-  args[14] = NULL;
-
-  ffi_call(&cif, FFI_FN(test_fn), &res, args);
-  /* { dg-output "5 6 10 11 12 13 14 7 8 uc=9 sc=10 11 12 13 14 15 16 2.120000 3.130000" } */
-  printf("res: %d\n", (int) res);
-  /* { dg-output "\nres: 42" } */
-
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_BAD_ARGTYPE);
   return 0;
 }
diff --git a/testsuite/libffi.call/va_2.c b/testsuite/libffi.call/va_2.c
new file mode 100644 (file)
index 0000000..0589d08
--- /dev/null
@@ -0,0 +1,196 @@
+/* Area:               ffi_call
+   Purpose:            Test passing struct in variable argument lists.
+   Limitations:        none.
+   PR:                 none.
+   Originator:         ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* m68k-*-* alpha-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+  unsigned char a;
+  unsigned char b;
+};
+
+struct large_tag
+{
+  unsigned a;
+  unsigned b;
+  unsigned c;
+  unsigned d;
+  unsigned e;
+};
+
+static int
+test_fn (int n, ...)
+{
+  va_list ap;
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l;
+  unsigned char uc;
+  signed char sc;
+  unsigned short us;
+  signed short ss;
+  unsigned int ui;
+  signed int si;
+  unsigned long ul;
+  signed long sl;
+  float f;
+  double d;
+
+  va_start (ap, n);
+  s1 = va_arg (ap, struct small_tag);
+  l = va_arg (ap, struct large_tag);
+  s2 = va_arg (ap, struct small_tag);
+
+  uc = va_arg (ap, unsigned);
+  sc = va_arg (ap, signed);
+
+  us = va_arg (ap, unsigned);
+  ss = va_arg (ap, signed);
+
+  ui = va_arg (ap, unsigned int);
+  si = va_arg (ap, signed int);
+
+  ul = va_arg (ap, unsigned long);
+  sl = va_arg (ap, signed long);
+
+  f = va_arg (ap, double);     /* C standard promotes float->double
+                                  when anonymous */
+  d = va_arg (ap, double);
+
+  printf ("%u %u %u %u %u %u %u %u %u uc=%u sc=%d %u %d %u %d %lu %ld %f %f\n",
+         s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+         s2.a, s2.b,
+         uc, sc,
+         us, ss,
+         ui, si,
+         ul, sl,
+         f, d);
+  va_end (ap);
+  return n + 1;
+}
+
+int
+main (void)
+{
+  ffi_cif cif;
+  void* args[15];
+  ffi_type* arg_types[15];
+
+  ffi_type s_type;
+  ffi_type *s_type_elements[3];
+
+  ffi_type l_type;
+  ffi_type *l_type_elements[6];
+
+  struct small_tag s1;
+  struct small_tag s2;
+  struct large_tag l1;
+
+  int n;
+  ffi_arg res;
+
+  unsigned int uc;
+  signed int sc;
+  unsigned int us;
+  signed int ss;
+  unsigned int ui;
+  signed int si;
+  unsigned long ul;
+  signed long sl;
+  double d1;
+  double f1;
+
+  s_type.size = 0;
+  s_type.alignment = 0;
+  s_type.type = FFI_TYPE_STRUCT;
+  s_type.elements = s_type_elements;
+
+  s_type_elements[0] = &ffi_type_uchar;
+  s_type_elements[1] = &ffi_type_uchar;
+  s_type_elements[2] = NULL;
+
+  l_type.size = 0;
+  l_type.alignment = 0;
+  l_type.type = FFI_TYPE_STRUCT;
+  l_type.elements = l_type_elements;
+
+  l_type_elements[0] = &ffi_type_uint;
+  l_type_elements[1] = &ffi_type_uint;
+  l_type_elements[2] = &ffi_type_uint;
+  l_type_elements[3] = &ffi_type_uint;
+  l_type_elements[4] = &ffi_type_uint;
+  l_type_elements[5] = NULL;
+
+  arg_types[0] = &ffi_type_sint;
+  arg_types[1] = &s_type;
+  arg_types[2] = &l_type;
+  arg_types[3] = &s_type;
+  arg_types[4] = &ffi_type_uint;
+  arg_types[5] = &ffi_type_sint;
+  arg_types[6] = &ffi_type_uint;
+  arg_types[7] = &ffi_type_sint;
+  arg_types[8] = &ffi_type_uint;
+  arg_types[9] = &ffi_type_sint;
+  arg_types[10] = &ffi_type_ulong;
+  arg_types[11] = &ffi_type_slong;
+  arg_types[12] = &ffi_type_double;
+  arg_types[13] = &ffi_type_double;
+  arg_types[14] = NULL;
+
+  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_OK);
+
+  s1.a = 5;
+  s1.b = 6;
+
+  l1.a = 10;
+  l1.b = 11;
+  l1.c = 12;
+  l1.d = 13;
+  l1.e = 14;
+
+  s2.a = 7;
+  s2.b = 8;
+
+  n = 41;
+
+  uc = 9;
+  sc = 10;
+  us = 11;
+  ss = 12;
+  ui = 13;
+  si = 14;
+  ul = 15;
+  sl = 16;
+  f1 = 2.12;
+  d1 = 3.13;
+
+  args[0] = &n;
+  args[1] = &s1;
+  args[2] = &l1;
+  args[3] = &s2;
+  args[4] = &uc;
+  args[5] = &sc;
+  args[6] = &us;
+  args[7] = &ss;
+  args[8] = &ui;
+  args[9] = &si;
+  args[10] = &ul;
+  args[11] = &sl;
+  args[12] = &f1;
+  args[13] = &d1;
+  args[14] = NULL;
+
+  ffi_call(&cif, FFI_FN(test_fn), &res, args);
+  /* { dg-output "5 6 10 11 12 13 14 7 8 uc=9 sc=10 11 12 13 14 15 16 2.120000 3.130000" } */
+  printf("res: %d\n", (int) res);
+  /* { dg-output "\nres: 42" } */
+
+  return 0;
+}
diff --git a/testsuite/libffi.closures/cls_uchar_va.c b/testsuite/libffi.closures/cls_uchar_va.c
deleted file mode 100644 (file)
index 6491c5b..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Area:       closure_call
-   Purpose:    Test anonymous unsigned char argument.
-   Limitations:        none.
-   PR:         none.
-   Originator: ARM Ltd. */
-
-/* { dg-do run } */
-#include "ffitest.h"
-
-typedef unsigned char T;
-
-static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
-                        void* userdata __UNUSED__)
- {
-   *(ffi_arg *)resp = *(T *)args[0];
-
-   printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]);
- }
-
-typedef T (*cls_ret_T)(T, ...);
-
-int main (void)
-{
-  ffi_cif cif;
-  void *code;
-  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
-  ffi_type * cl_arg_types[3];
-  T res;
-
-  cl_arg_types[0] = &ffi_type_uchar;
-  cl_arg_types[1] = &ffi_type_uchar;
-  cl_arg_types[2] = NULL;
-
-  /* Initialize the cif */
-  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
-                        &ffi_type_uchar, cl_arg_types) == FFI_OK);
-
-  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
-  res = ((((cls_ret_T)code)(67, 4)));
-  /* { dg-output "67: 67 4" } */
-  printf("res: %d\n", res);
-  /* { dg-output "\nres: 67" } */
-  exit(0);
-}
diff --git a/testsuite/libffi.closures/cls_ushort_va.c b/testsuite/libffi.closures/cls_ushort_va.c
deleted file mode 100644 (file)
index 37aa106..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Area:       closure_call
-   Purpose:    Test anonymous unsigned short argument.
-   Limitations:        none.
-   PR:         none.
-   Originator: ARM Ltd. */
-
-/* { dg-do run } */
-#include "ffitest.h"
-
-typedef unsigned short T;
-
-static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
-                        void* userdata __UNUSED__)
- {
-   *(ffi_arg *)resp = *(T *)args[0];
-
-   printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]);
- }
-
-typedef T (*cls_ret_T)(T, ...);
-
-int main (void)
-{
-  ffi_cif cif;
-  void *code;
-  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
-  ffi_type * cl_arg_types[3];
-  T res;
-
-  cl_arg_types[0] = &ffi_type_ushort;
-  cl_arg_types[1] = &ffi_type_ushort;
-  cl_arg_types[2] = NULL;
-
-  /* Initialize the cif */
-  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
-                        &ffi_type_ushort, cl_arg_types) == FFI_OK);
-
-  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
-  res = ((((cls_ret_T)code)(67, 4)));
-  /* { dg-output "67: 67 4" } */
-  printf("res: %d\n", res);
-  /* { dg-output "\nres: 67" } */
-  exit(0);
-}