# HG changeset patch
# User Tassilo Philipp
# Date 1655716509 -7200
# Node ID 0455834d29a18995d7e5390c291bf97e40d3f2d5
# Parent  a6d00ee46731371ec3afe556bd75482bdf6ba9ff
- dyncallback: x64/sysv buffer overflow fix for aggregate args whose size isn't a multiple of 8

diff -r a6d00ee46731 -r 0455834d29a1 dyncallback/dyncall_args_x64.c
--- a/dyncallback/dyncall_args_x64.c	Mon Jun 20 11:04:20 2022 +0200
+++ b/dyncallback/dyncall_args_x64.c	Mon Jun 20 11:15:09 2022 +0200
@@ -100,7 +100,7 @@
   if(ag->sysv_classes[0] == SYSVC_MEMORY || (n_regs.i > numIntRegs) || (n_regs.f > numFloatRegs))
   {
      memcpy(target, p->stack_ptr, ag->size);
-     p->stack_ptr = p->stack_ptr + ((ag->size + (sizeof(DClonglong)-1)) >> 3); // advance to next full stack slot
+     p->stack_ptr = p->stack_ptr + ((ag->size + (sizeof(DClonglong)-1)) >> 3); /* advance to next full stack slot */
   }
   else
   {
@@ -108,8 +108,21 @@
     {
       switch (ag->sysv_classes[i])
       {
-        case SYSVC_INTEGER: ((DClonglong*)target)[i] = dcbArgLongLong(p); break;
-        case SYSVC_SSE:     ((DCdouble  *)target)[i] = dcbArgDouble  (p); break;
+        case SYSVC_INTEGER:
+          switch (ag->size - i*8) {
+            case 1:  *(DCchar *)(((DClonglong*)target) + i) = dcbArgChar    (p); break;
+            case 2:  *(DCshort*)(((DClonglong*)target) + i) = dcbArgShort   (p); break;
+            case 4:  *(DCint  *)(((DClonglong*)target) + i) = dcbArgInt     (p); break;
+            default: *          (((DClonglong*)target) + i) = dcbArgLongLong(p); break;
+          }
+          break;
+
+        case SYSVC_SSE:
+          switch (ag->size - i*8) {
+            case 4:  *(DCfloat*)(((DCdouble*)target) + i) = dcbArgFloat (p); break;
+            default: *          (((DCdouble*)target) + i) = dcbArgDouble(p); break;
+          }
+          break;
         /* @@@AGGR implement when implementing x87 types */
         default:
             assert(DC_FALSE && "Should never be reached because we check for unupported classes earlier");