diff options
author | David Malcolm <dmalcolm@redhat.com> | 2023-10-26 15:56:13 -0400 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2023-10-26 15:57:40 -0400 |
commit | cd7dadcd2759d195b75f4dba3e17b638ed92db68 (patch) | |
tree | 39d04e8f1d5b6025ee5e47a4842c1d92a6c265ae /gcc/c-family | |
parent | 46f51bd73b77e572eb647eb56eddff663dd5e954 (diff) | |
download | gcc-cd7dadcd2759d195b75f4dba3e17b638ed92db68.zip gcc-cd7dadcd2759d195b75f4dba3e17b638ed92db68.tar.gz gcc-cd7dadcd2759d195b75f4dba3e17b638ed92db68.tar.bz2 |
Add attribute((null_terminated_string_arg(PARAM_IDX)))
This patch adds a new function attribute to GCC for marking that an
argument is expected to be a null-terminated string.
For example, consider:
void test_a (const char *p)
__attribute__((null_terminated_string_arg (1)));
which would indicate to humans and compilers that argument 1 of "test_a"
is expected to be a null-terminated string, with the idea:
- we should complain if it's not valid to read from *p up to the first
'\0' character in the buffer
- we should complain if *p is not terminated, or if it's uninitialized
before the first '\0' character
This is independent of the nonnull-ness of the pointer: if you also want
to express that the argument must be non-null, we already have
__attribute__((nonnull (N))), so the user can write e.g.:
void test_b (const char *p)
__attribute__((null_terminated_string_arg (1))
__attribute__((nonnull (1)));
which can also be spelled as:
void test_b (const char *p)
__attribute__((null_terminated_string_arg (1),
nonnull (1)));
For a function similar to strncpy, we can use the "access" attribute to
express a maximum size of the read:
void test_c (const char *p, size_t sz)
__attribute__((null_terminated_string_arg (1),
nonnull (1),
access (read_only, 1, 2)));
The patch implements:
(a) C/C++ frontends: recognition of this attribute
(b) analyzer: usage of this attribute
gcc/analyzer/ChangeLog:
* region-model.cc
(region_model::check_external_function_for_access_attr): Split
out, replacing with...
(region_model::check_function_attr_access): ...this new function
and...
(region_model::check_function_attrs): ...this new function.
(region_model::check_one_function_attr_null_terminated_string_arg):
New.
(region_model::check_function_attr_null_terminated_string_arg):
New.
(region_model::handle_unrecognized_call): Update for renaming of
check_external_function_for_access_attr to check_function_attrs.
(region_model::check_for_null_terminated_string_arg): Add return
value to one overload. Make both overloads const.
* region-model.h: Include "stringpool.h" and "attribs.h".
(region_model::check_for_null_terminated_string_arg): Add return
value to one overload. Make both overloads const.
(region_model::check_external_function_for_access_attr): Delete
decl.
(region_model::check_function_attr_access): New decl.
(region_model::check_function_attr_null_terminated_string_arg):
New decl.
(region_model::check_one_function_attr_null_terminated_string_arg):
New decl.
(region_model::check_function_attrs): New decl.
gcc/c-family/ChangeLog:
* c-attribs.cc (c_common_attribute_table): Add
"null_terminated_string_arg".
(handle_null_terminated_string_arg_attribute): New.
gcc/ChangeLog:
* doc/extend.texi (Common Function Attributes): Add
null_terminated_string_arg.
gcc/testsuite/ChangeLog:
* c-c++-common/analyzer/attr-null_terminated_string_arg-access-read_write.c:
New test.
* c-c++-common/analyzer/attr-null_terminated_string_arg-access-without-size.c:
New test.
* c-c++-common/analyzer/attr-null_terminated_string_arg-multiple.c:
New test.
* c-c++-common/analyzer/attr-null_terminated_string_arg-nonnull-2.c:
New test.
* c-c++-common/analyzer/attr-null_terminated_string_arg-nonnull-sized.c:
New test.
* c-c++-common/analyzer/attr-null_terminated_string_arg-nonnull.c:
New test.
* c-c++-common/analyzer/attr-null_terminated_string_arg-nullable-sized.c:
New test.
* c-c++-common/analyzer/attr-null_terminated_string_arg-nullable.c:
New test.
* c-c++-common/attr-null_terminated_string_arg.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/c-attribs.cc | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index abf44d5..a041c3b 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -178,6 +178,7 @@ static tree handle_signed_bool_precision_attribute (tree *, tree, tree, int, bool *); static tree handle_retain_attribute (tree *, tree, tree, int, bool *); static tree handle_fd_arg_attribute (tree *, tree, tree, int, bool *); +static tree handle_null_terminated_string_arg_attribute (tree *, tree, tree, int, bool *); /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ @@ -572,6 +573,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_fd_arg_attribute, NULL}, { "fd_arg_write", 1, 1, false, true, true, false, handle_fd_arg_attribute, NULL}, + { "null_terminated_string_arg", 1, 1, false, true, true, false, + handle_null_terminated_string_arg_attribute, NULL}, { NULL, 0, 0, false, false, false, false, NULL, NULL } }; @@ -4660,6 +4663,20 @@ handle_fd_arg_attribute (tree *node, tree name, tree args, return NULL_TREE; } +/* Handle the "null_terminated_string_arg" attribute. */ + +static tree +handle_null_terminated_string_arg_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + if (positional_argument (*node, name, TREE_VALUE (args), POINTER_TYPE)) + return NULL_TREE; + + *no_add_attrs = true; + return NULL_TREE; +} + /* Handle the "nonstring" variable attribute. */ static tree |