libctf, create: do not corrupt function types' arglists at insertion time
authorNick Alcock <nick.alcock@oracle.com>
Tue, 2 Jun 2020 19:17:51 +0000 (20:17 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Wed, 22 Jul 2020 16:57:22 +0000 (17:57 +0100)
ctf_add_function assumes that function types' arglists are of type
ctf_id_t.  Since they are CTF IDs, they are 32 bits wide, a uint32_t:
unfortunately ctf_id_t is a forward-compatible user-facing 64 bits wide,
and should never ever reach the CTF storage level.

All the CTF code other than ctf_add_function correctly assumes that
function arglists outside dynamic containers are 32 bits wide, so the
serialization machinery ends up cutting off half the arglist, corrupting
all args but the first (a good sign is a bunch of args of ID 0, the
unimplemented type, popping up).

Fix this by copying the arglist into place item by item, casting it
properly, at the same time as we validate the arg types.  Fix the type
of the dtu_argv in the dynamic container and drop the now-unnecessary
cast in the serializer.

libctf/
* ctf-impl.h (ctf_dtdef_t) <dtu_argv>: Fix type.
* ctf-create.c (ctf_add_function): Check for unimplemented type
and populate at the same time.  Populate one-by-one, not via
memcpy.
(ctf_serialize): Remove unnecessary cast.
* ctf-types.c (ctf_func_type_info): Likewise.
(ctf_func_type_args): Likewise.  Fix comment typo.

libctf/ChangeLog
libctf/ctf-create.c
libctf/ctf-impl.h
libctf/ctf-types.c

index cca704a4ec231137144f7744b00477ae2be8b522..39cf47d0b3685ad503f2bd9a31894d1ed3fbd35e 100644 (file)
@@ -1,3 +1,13 @@
+2020-07-22  Nick Alcock  <nick.alcock@oracle.com>
+
+       * ctf-impl.h (ctf_dtdef_t) <dtu_argv>: Fix type.
+       * ctf-create.c (ctf_add_function): Check for unimplemented type
+       and populate at the same time.  Populate one-by-one, not via
+       memcpy.
+       (ctf_serialize): Remove unnecessary cast.
+       * ctf-types.c (ctf_func_type_info): Likewise.
+       (ctf_func_type_args): Likewise.  Fix comment typo.
+
 2020-07-22  Nick Alcock  <nick.alcock@oracle.com>
 
        * ctf-create.c (ctf_add_reftype): Support refs to type zero.
index 67a3f199a961f6882cee406796b91ef80cb6bda9..f91da6ea15951ec0864bc28d60178acaa9a0dd6c 100644 (file)
@@ -448,7 +448,7 @@ ctf_serialize (ctf_file_t *fp)
            uint32_t argc;
 
            for (argc = 0; argc < vlen; argc++)
-             *argv++ = (uint32_t) dtd->dtd_u.dtu_argv[argc];
+             *argv++ = dtd->dtd_u.dtu_argv[argc];
 
            if (vlen & 1)
              *argv++ = 0;      /* Pad to 4-byte boundary.  */
@@ -1052,7 +1052,7 @@ ctf_add_function (ctf_file_t *fp, uint32_t flag,
   ctf_dtdef_t *dtd;
   ctf_id_t type;
   uint32_t vlen;
-  ctf_id_t *vdat = NULL;
+  uint32_t *vdat = NULL;
   ctf_file_t *tmp = fp;
   size_t i;
 
@@ -1068,19 +1068,23 @@ ctf_add_function (ctf_file_t *fp, uint32_t flag,
       && ctf_lookup_by_id (&tmp, ctc->ctc_return) == NULL)
     return CTF_ERR;            /* errno is set for us.  */
 
-  for (i = 0; i < ctc->ctc_argc; i++)
-    {
-      tmp = fp;
-      if (argv[i] != 0 && ctf_lookup_by_id (&tmp, argv[i]) == NULL)
-       return CTF_ERR;         /* errno is set for us.  */
-    }
-
   if (vlen > CTF_MAX_VLEN)
     return (ctf_set_errno (fp, EOVERFLOW));
 
   if (vlen != 0 && (vdat = malloc (sizeof (ctf_id_t) * vlen)) == NULL)
     return (ctf_set_errno (fp, EAGAIN));
 
+  for (i = 0; i < ctc->ctc_argc; i++)
+    {
+      tmp = fp;
+      if (argv[i] != 0 && ctf_lookup_by_id (&tmp, argv[i]) == NULL)
+       {
+         free (vdat);
+         return CTF_ERR;          /* errno is set for us.  */
+       }
+      vdat[i] = (uint32_t) argv[i];
+    }
+
   if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_FUNCTION,
                               &dtd)) == CTF_ERR)
     {
@@ -1091,7 +1095,6 @@ ctf_add_function (ctf_file_t *fp, uint32_t flag,
   dtd->dtd_data.ctt_info = CTF_TYPE_INFO (CTF_K_FUNCTION, flag, vlen);
   dtd->dtd_data.ctt_type = (uint32_t) ctc->ctc_return;
 
-  memcpy (vdat, argv, sizeof (ctf_id_t) * ctc->ctc_argc);
   if (ctc->ctc_flags & CTF_FUNC_VARARG)
     vdat[vlen - 1] = 0;                   /* Add trailing zero to indicate varargs.  */
   dtd->dtd_u.dtu_argv = vdat;
index b20a4f05a80b3f3832b3e8a258a60178ff043564..fdd48f0d3316b3313143a6bed1560222f329de01 100644 (file)
@@ -172,7 +172,7 @@ typedef struct ctf_dtdef
     ctf_list_t dtu_members;    /* struct, union, or enum */
     ctf_arinfo_t dtu_arr;      /* array */
     ctf_encoding_t dtu_enc;    /* integer or float */
-    ctf_id_t *dtu_argv;                /* function */
+    uint32_t *dtu_argv;                /* function */
     ctf_slice_t dtu_slice;     /* slice */
   } dtd_u;
 } ctf_dtdef_t;
index cd910434ea41abcf72bdee6c19b5d8b9f22cd05b..35253cb3cbc4d802c3c66e702e5120cacea871e2 100644 (file)
@@ -1163,7 +1163,7 @@ ctf_func_type_info (ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
   if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
     args = (uint32_t *) ((uintptr_t) tp + increment);
   else
-    args = (uint32_t *) dtd->dtd_u.dtu_argv;
+    args = dtd->dtd_u.dtu_argv;
 
   if (fip->ctc_argc != 0 && args[fip->ctc_argc - 1] == 0)
     {
@@ -1174,7 +1174,7 @@ ctf_func_type_info (ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
   return 0;
 }
 
-/* Given a type ID relating to a function type,, return the arguments for the
+/* Given a type ID relating to a function type, return the arguments for the
    function.  */
 
 int
@@ -1200,7 +1200,7 @@ ctf_func_type_args (ctf_file_t *fp, ctf_id_t type, uint32_t argc, ctf_id_t *argv
   if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
     args = (uint32_t *) ((uintptr_t) tp + increment);
   else
-    args = (uint32_t *) dtd->dtd_u.dtu_argv;
+    args = dtd->dtd_u.dtu_argv;
 
   for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--)
     *argv++ = *args++;