libctf: create: non-root-visible types should not appear in name tables

We were accidentally interning newly-added and newly-opened
non-root-visible types into name tables, and removing names from name
tables when such types were removed.  This is very wrong: the whole
point of non-root-visible types is they do not go in name tables and
cannot be looked up by name.  This bug made non-root-visible types
basically identical to root-visible types, right back to the earliest
days of libctf in the Solaris era.

libctf/
	* ctf-open.c (init_types): Only intern root-visible types.
	* ctf-create.c (ctf_dtd_insert): Likewise.
	(ctf_dtd_delete): Only remove root-visible types.
	(ctf_rollback): Likewise.
	(ctf_add_generic): Adjust.
	(ctf_add_struct_sized): Adjust comment.
	(ctf_add_union_sized): Likewise.
	(ctf_add_enum): Likewise.
	* ctf-impl.h (ctf_dtd_insert): Adjust prototype.
This commit is contained in:
Nick Alcock 2019-10-21 11:27:43 +01:00
parent 094e34f221
commit fe4c2d5563
4 changed files with 53 additions and 17 deletions

View file

@ -1,3 +1,15 @@
2020-06-26 Nick Alcock <nick.alcock@oracle.com>
* ctf-open.c (init_types): Only intern root-visible types.
* ctf-create.c (ctf_dtd_insert): Likewise.
(ctf_dtd_delete): Only remove root-visible types.
(ctf_rollback): Likewise.
(ctf_add_generic): Adjust.
(ctf_add_struct_sized): Adjust comment.
(ctf_add_union_sized): Likewise.
(ctf_add_enum): Likewise.
* ctf-impl.h (ctf_dtd_insert): Adjust prototype.
2020-03-11 John Baldwin <jhb@FreeBSD.org> 2020-03-11 John Baldwin <jhb@FreeBSD.org>
* swap.h (bswap_identity_64): Make static. * swap.h (bswap_identity_64): Make static.

View file

@ -597,13 +597,13 @@ ctf_name_table (ctf_file_t *fp, int kind)
} }
int int
ctf_dtd_insert (ctf_file_t *fp, ctf_dtdef_t *dtd, int kind) ctf_dtd_insert (ctf_file_t *fp, ctf_dtdef_t *dtd, int flag, int kind)
{ {
const char *name; const char *name;
if (ctf_dynhash_insert (fp->ctf_dthash, (void *) dtd->dtd_type, dtd) < 0) if (ctf_dynhash_insert (fp->ctf_dthash, (void *) dtd->dtd_type, dtd) < 0)
return -1; return -1;
if (dtd->dtd_data.ctt_name if (flag == CTF_ADD_ROOT && dtd->dtd_data.ctt_name
&& (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL) && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL)
{ {
if (ctf_dynhash_insert (ctf_name_table (fp, kind)->ctn_writable, if (ctf_dynhash_insert (ctf_name_table (fp, kind)->ctn_writable,
@ -646,7 +646,8 @@ ctf_dtd_delete (ctf_file_t *fp, ctf_dtdef_t *dtd)
} }
if (dtd->dtd_data.ctt_name if (dtd->dtd_data.ctt_name
&& (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL) && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL
&& LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info))
{ {
ctf_dynhash_remove (ctf_name_table (fp, kind)->ctn_writable, ctf_dynhash_remove (ctf_name_table (fp, kind)->ctn_writable,
name); name);
@ -762,7 +763,8 @@ ctf_rollback (ctf_file_t *fp, ctf_snapshot_id_t id)
kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info); kind = LCTF_INFO_KIND (fp, dtd->dtd_data.ctt_info);
if (dtd->dtd_data.ctt_name if (dtd->dtd_data.ctt_name
&& (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL) && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL
&& LCTF_INFO_ISROOT (fp, dtd->dtd_data.ctt_info))
{ {
ctf_dynhash_remove (ctf_name_table (fp, kind)->ctn_writable, ctf_dynhash_remove (ctf_name_table (fp, kind)->ctn_writable,
name); name);
@ -831,7 +833,7 @@ ctf_add_generic (ctf_file_t *fp, uint32_t flag, const char *name, int kind,
return (ctf_set_errno (fp, EAGAIN)); return (ctf_set_errno (fp, EAGAIN));
} }
if (ctf_dtd_insert (fp, dtd, kind) < 0) if (ctf_dtd_insert (fp, dtd, flag, kind) < 0)
{ {
free (dtd); free (dtd);
return CTF_ERR; /* errno is set for us. */ return CTF_ERR; /* errno is set for us. */
@ -1094,8 +1096,7 @@ ctf_add_struct_sized (ctf_file_t *fp, uint32_t flag, const char *name,
ctf_dtdef_t *dtd; ctf_dtdef_t *dtd;
ctf_id_t type = 0; ctf_id_t type = 0;
/* Promote forwards to structs. */ /* Promote root-visible forwards to structs. */
if (name != NULL) if (name != NULL)
type = ctf_lookup_by_rawname (fp, CTF_K_STRUCT, name); type = ctf_lookup_by_rawname (fp, CTF_K_STRUCT, name);
@ -1132,7 +1133,7 @@ ctf_add_union_sized (ctf_file_t *fp, uint32_t flag, const char *name,
ctf_dtdef_t *dtd; ctf_dtdef_t *dtd;
ctf_id_t type = 0; ctf_id_t type = 0;
/* Promote forwards to unions. */ /* Promote root-visible forwards to unions. */
if (name != NULL) if (name != NULL)
type = ctf_lookup_by_rawname (fp, CTF_K_UNION, name); type = ctf_lookup_by_rawname (fp, CTF_K_UNION, name);
@ -1168,7 +1169,7 @@ ctf_add_enum (ctf_file_t *fp, uint32_t flag, const char *name)
ctf_dtdef_t *dtd; ctf_dtdef_t *dtd;
ctf_id_t type = 0; ctf_id_t type = 0;
/* Promote forwards to enums. */ /* Promote root-visible forwards to enums. */
if (name != NULL) if (name != NULL)
type = ctf_lookup_by_rawname (fp, CTF_K_ENUM, name); type = ctf_lookup_by_rawname (fp, CTF_K_ENUM, name);

View file

@ -399,7 +399,7 @@ extern void ctf_list_prepend (ctf_list_t *, void *);
extern void ctf_list_delete (ctf_list_t *, void *); extern void ctf_list_delete (ctf_list_t *, void *);
extern int ctf_list_empty_p (ctf_list_t *lp); extern int ctf_list_empty_p (ctf_list_t *lp);
extern int ctf_dtd_insert (ctf_file_t *, ctf_dtdef_t *, int); extern int ctf_dtd_insert (ctf_file_t *, ctf_dtdef_t *, int flag, int kind);
extern void ctf_dtd_delete (ctf_file_t *, ctf_dtdef_t *); extern void ctf_dtd_delete (ctf_file_t *, ctf_dtdef_t *);
extern ctf_dtdef_t *ctf_dtd_lookup (const ctf_file_t *, ctf_id_t); extern ctf_dtdef_t *ctf_dtd_lookup (const ctf_file_t *, ctf_id_t);
extern ctf_dtdef_t *ctf_dynamic_type (const ctf_file_t *, ctf_id_t); extern ctf_dtdef_t *ctf_dynamic_type (const ctf_file_t *, ctf_id_t);

View file

@ -765,7 +765,7 @@ init_types (ctf_file_t *fp, ctf_header_t *cth)
for (id = 1, tp = tbuf; tp < tend; xp++, id++) for (id = 1, tp = tbuf; tp < tend; xp++, id++)
{ {
unsigned short kind = LCTF_INFO_KIND (fp, tp->ctt_info); unsigned short kind = LCTF_INFO_KIND (fp, tp->ctt_info);
unsigned short flag = LCTF_INFO_ISROOT (fp, tp->ctt_info); unsigned short isroot = LCTF_INFO_ISROOT (fp, tp->ctt_info);
unsigned long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info); unsigned long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info);
ssize_t size, increment, vbytes; ssize_t size, increment, vbytes;
@ -787,7 +787,7 @@ init_types (ctf_file_t *fp, ctf_header_t *cth)
if (((ctf_hash_lookup_type (fp->ctf_names.ctn_readonly, if (((ctf_hash_lookup_type (fp->ctf_names.ctn_readonly,
fp, name)) == 0) fp, name)) == 0)
|| (flag & CTF_ADD_ROOT)) || isroot)
{ {
err = ctf_hash_define_type (fp->ctf_names.ctn_readonly, fp, err = ctf_hash_define_type (fp->ctf_names.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
@ -804,6 +804,9 @@ init_types (ctf_file_t *fp, ctf_header_t *cth)
break; break;
case CTF_K_FUNCTION: case CTF_K_FUNCTION:
if (!isroot)
break;
err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp, err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
@ -812,6 +815,12 @@ init_types (ctf_file_t *fp, ctf_header_t *cth)
break; break;
case CTF_K_STRUCT: case CTF_K_STRUCT:
if (size >= CTF_LSTRUCT_THRESH)
nlstructs++;
if (!isroot)
break;
err = ctf_hash_define_type (fp->ctf_structs.ctn_readonly, fp, err = ctf_hash_define_type (fp->ctf_structs.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
@ -819,23 +828,27 @@ init_types (ctf_file_t *fp, ctf_header_t *cth)
if (err != 0) if (err != 0)
return err; return err;
if (size >= CTF_LSTRUCT_THRESH)
nlstructs++;
break; break;
case CTF_K_UNION: case CTF_K_UNION:
if (size >= CTF_LSTRUCT_THRESH)
nlunions++;
if (!isroot)
break;
err = ctf_hash_define_type (fp->ctf_unions.ctn_readonly, fp, err = ctf_hash_define_type (fp->ctf_unions.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
if (err != 0) if (err != 0)
return err; return err;
if (size >= CTF_LSTRUCT_THRESH)
nlunions++;
break; break;
case CTF_K_ENUM: case CTF_K_ENUM:
if (!isroot)
break;
err = ctf_hash_define_type (fp->ctf_enums.ctn_readonly, fp, err = ctf_hash_define_type (fp->ctf_enums.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
@ -845,6 +858,9 @@ init_types (ctf_file_t *fp, ctf_header_t *cth)
break; break;
case CTF_K_TYPEDEF: case CTF_K_TYPEDEF:
if (!isroot)
break;
err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp, err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);
@ -855,6 +871,10 @@ init_types (ctf_file_t *fp, ctf_header_t *cth)
case CTF_K_FORWARD: case CTF_K_FORWARD:
{ {
ctf_names_t *np = ctf_name_table (fp, tp->ctt_type); ctf_names_t *np = ctf_name_table (fp, tp->ctt_type);
if (!isroot)
break;
/* Only insert forward tags into the given hash if the type or tag /* Only insert forward tags into the given hash if the type or tag
name is not already present. */ name is not already present. */
if (ctf_hash_lookup_type (np->ctn_readonly, fp, name) == 0) if (ctf_hash_lookup_type (np->ctn_readonly, fp, name) == 0)
@ -881,6 +901,9 @@ init_types (ctf_file_t *fp, ctf_header_t *cth)
case CTF_K_VOLATILE: case CTF_K_VOLATILE:
case CTF_K_CONST: case CTF_K_CONST:
case CTF_K_RESTRICT: case CTF_K_RESTRICT:
if (!isroot)
break;
err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp, err = ctf_hash_insert_type (fp->ctf_names.ctn_readonly, fp,
LCTF_INDEX_TO_TYPE (fp, id, child), LCTF_INDEX_TO_TYPE (fp, id, child),
tp->ctt_name); tp->ctt_name);