libctf: lookup_by_name: do not return success for nonexistent pointer types
authorNick Alcock <nick.alcock@oracle.com>
Tue, 19 Jan 2021 12:45:18 +0000 (12:45 +0000)
committerNick Alcock <nick.alcock@oracle.com>
Tue, 19 Jan 2021 12:45:19 +0000 (12:45 +0000)
The recent work allowing lookups of pointers in child dicts when the
pointed-to type is in the parent dict broke the case where a pointer
type that does not exist at all is looked up: we mistakenly return the
pointed-to type, which is likely not a pointer at all.  This causes
considerable confusion.

Fixed, with a new testcase.

libctf/ChangeLog
2021-01-19  Nick Alcock  <nick.alcock@oracle.com>

* ctf-lookup.c (ctf_lookup_by_name_internal): Do not return the
base type if looking up a nonexistent pointer type.
* testsuite/libctf-regression/pptrtab*: Test it.

libctf/ChangeLog
libctf/ctf-lookup.c
libctf/testsuite/libctf-regression/pptrtab-a.c
libctf/testsuite/libctf-regression/pptrtab-b.c
libctf/testsuite/libctf-regression/pptrtab.c

index aa021fa808de136a186f122d24851c2ed8333ce1..b48cc0504062b229dae0a97aa9830b20fb8e3157 100644 (file)
@@ -1,3 +1,9 @@
+2021-01-19  Nick Alcock  <nick.alcock@oracle.com>
+
+       * ctf-lookup.c (ctf_lookup_by_name_internal): Do not return the
+       base type if looking up a nonexistent pointer type.
+       * testsuite/libctf-regression/pptrtab*: Test it.
+
 2021-01-13  Alan Modra  <amodra@gmail.com>
 
        * Makefile.in: Regenerate.
index c7f7e2978221c6929227111a550a8c11370e57dc..6d4e085838c0b205cc75dadf38042c573042c7d3 100644 (file)
@@ -184,24 +184,36 @@ ctf_lookup_by_name_internal (ctf_dict_t *fp, ctf_dict_t *child,
             from resolving the type down to its base type and use that instead.
             This helps with cases where the CTF data includes "struct foo *"
             but not "foo_t *" and the user tries to access "foo_t *" in the
-            debugger.  */
+            debugger.
+
+            There is extra complexity here because uninitialized elements in
+            the pptrtab and ptrtab are set to zero, but zero (as the type ID
+            meaning the unimplemented type) is a valid return type from
+            ctf_lookup_by_name.  (Pointers to types are never of type 0, so
+            this is unambiguous, just fiddly to deal with.)  */
 
          uint32_t idx = LCTF_TYPE_TO_INDEX (fp, type);
          int in_child = 0;
 
-         ntype = type;
+         ntype = CTF_ERR;
          if (child && idx <= child->ctf_pptrtab_len)
            {
              ntype = child->ctf_pptrtab[idx];
              if (ntype)
                in_child = 1;
+             else
+               ntype = CTF_ERR;
            }
 
-         if (ntype == 0)
-           ntype = fp->ctf_ptrtab[idx];
+         if (ntype == CTF_ERR)
+           {
+             ntype = fp->ctf_ptrtab[idx];
+             if (ntype == 0)
+               ntype = CTF_ERR;
+           }
 
          /* Try resolving to its base type and check again.  */
-         if (ntype == 0)
+         if (ntype == CTF_ERR)
            {
              if (child)
                ntype = ctf_type_resolve_unsliced (child, type);
@@ -213,16 +225,22 @@ ctf_lookup_by_name_internal (ctf_dict_t *fp, ctf_dict_t *child,
 
              idx = LCTF_TYPE_TO_INDEX (fp, ntype);
 
-             ntype = 0;
+             ntype = CTF_ERR;
              if (child && idx <= child->ctf_pptrtab_len)
                {
                  ntype = child->ctf_pptrtab[idx];
                  if (ntype)
                    in_child = 1;
+                 else
+                   ntype = CTF_ERR;
                }
 
-             if (ntype == 0)
-               ntype = fp->ctf_ptrtab[idx];
+             if (ntype == CTF_ERR)
+               {
+                 ntype = fp->ctf_ptrtab[idx];
+                 if (ntype == 0)
+                   ntype = CTF_ERR;
+               }
              if (ntype == CTF_ERR)
                goto notype;
            }
index e9f656a0bc8f1a51e80ad5b490d43885c82177fb..654148771149bae5a4160255feee21306c03934d 100644 (file)
@@ -1,3 +1,5 @@
 typedef long a_t;
+typedef long b_t;
 
 a_t *a;
+b_t ignore2;
index 6142f194c190da12f7b328e57febd3a04f84d433..e458021efb13b4b2bff65e9fe30b258030a6dd9d 100644 (file)
@@ -1,4 +1,5 @@
 typedef long a_t;
+typedef long b_t;
 
 a_t b;
-
+b_t ignore1;
index 5d3c2f2ee93d9404669ce75154ee1483cc5eb04d..fe1b8fe2b4344f676237417614e505f110f74a98 100644 (file)
@@ -23,13 +23,18 @@ main (int argc, char *argv[])
     goto open_err;
 
   /* Make sure we can look up a_t * by name in all non-parent dicts, even though
-     the a_t * and the type it points to are in distinct dicts.  */
+     the a_t * and the type it points to are in distinct dicts; make sure we
+     cannot look up b_t *.  */
 
   while ((fp = ctf_archive_next (ctf, &i, &arcname, 1, &err)) != NULL)
     {
       if ((type = ctf_lookup_by_name (fp, "a_t *")) == CTF_ERR)
        goto err;
 
+      if ((ctf_lookup_by_name (fp, "b_t *")) != CTF_ERR ||
+          ctf_errno (fp) != ECTF_NOTYPE)
+       goto noerr;
+
       if (ctf_type_reference (fp, type) == CTF_ERR)
        goto err;
 
@@ -51,4 +56,7 @@ main (int argc, char *argv[])
  err:
   fprintf (stderr, "Lookup failed in %s: %s\n", arcname, ctf_errmsg (ctf_errno (fp)));
   return 1;
+ noerr:
+  fprintf (stderr, "Lookup unexpectedly succeeded in %s\n", arcname);
+  return 1;
 }