libctf: lookup_by_name: do not return success for nonexistent pointer types

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.
This commit is contained in:
Nick Alcock 2021-01-19 12:45:18 +00:00
parent c98de297b3
commit e05a3e5a49
5 changed files with 45 additions and 10 deletions

View 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> 2021-01-13 Alan Modra <amodra@gmail.com>
* Makefile.in: Regenerate. * Makefile.in: Regenerate.

View 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. from resolving the type down to its base type and use that instead.
This helps with cases where the CTF data includes "struct foo *" 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 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); uint32_t idx = LCTF_TYPE_TO_INDEX (fp, type);
int in_child = 0; int in_child = 0;
ntype = type; ntype = CTF_ERR;
if (child && idx <= child->ctf_pptrtab_len) if (child && idx <= child->ctf_pptrtab_len)
{ {
ntype = child->ctf_pptrtab[idx]; ntype = child->ctf_pptrtab[idx];
if (ntype) if (ntype)
in_child = 1; in_child = 1;
else
ntype = CTF_ERR;
} }
if (ntype == 0) if (ntype == CTF_ERR)
ntype = fp->ctf_ptrtab[idx]; {
ntype = fp->ctf_ptrtab[idx];
if (ntype == 0)
ntype = CTF_ERR;
}
/* Try resolving to its base type and check again. */ /* Try resolving to its base type and check again. */
if (ntype == 0) if (ntype == CTF_ERR)
{ {
if (child) if (child)
ntype = ctf_type_resolve_unsliced (child, type); 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); idx = LCTF_TYPE_TO_INDEX (fp, ntype);
ntype = 0; ntype = CTF_ERR;
if (child && idx <= child->ctf_pptrtab_len) if (child && idx <= child->ctf_pptrtab_len)
{ {
ntype = child->ctf_pptrtab[idx]; ntype = child->ctf_pptrtab[idx];
if (ntype) if (ntype)
in_child = 1; in_child = 1;
else
ntype = CTF_ERR;
} }
if (ntype == 0) if (ntype == CTF_ERR)
ntype = fp->ctf_ptrtab[idx]; {
ntype = fp->ctf_ptrtab[idx];
if (ntype == 0)
ntype = CTF_ERR;
}
if (ntype == CTF_ERR) if (ntype == CTF_ERR)
goto notype; goto notype;
} }

View file

@ -1,3 +1,5 @@
typedef long a_t; typedef long a_t;
typedef long b_t;
a_t *a; a_t *a;
b_t ignore2;

View file

@ -1,4 +1,5 @@
typedef long a_t; typedef long a_t;
typedef long b_t;
a_t b; a_t b;
b_t ignore1;

View file

@ -23,13 +23,18 @@ main (int argc, char *argv[])
goto open_err; goto open_err;
/* Make sure we can look up a_t * by name in all non-parent dicts, even though /* 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) while ((fp = ctf_archive_next (ctf, &i, &arcname, 1, &err)) != NULL)
{ {
if ((type = ctf_lookup_by_name (fp, "a_t *")) == CTF_ERR) if ((type = ctf_lookup_by_name (fp, "a_t *")) == CTF_ERR)
goto 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) if (ctf_type_reference (fp, type) == CTF_ERR)
goto err; goto err;
@ -51,4 +56,7 @@ main (int argc, char *argv[])
err: err:
fprintf (stderr, "Lookup failed in %s: %s\n", arcname, ctf_errmsg (ctf_errno (fp))); fprintf (stderr, "Lookup failed in %s: %s\n", arcname, ctf_errmsg (ctf_errno (fp)));
return 1; return 1;
noerr:
fprintf (stderr, "Lookup unexpectedly succeeded in %s\n", arcname);
return 1;
} }