aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family/c-attribs.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2023-10-26 15:56:13 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2023-10-26 15:57:40 -0400
commitcd7dadcd2759d195b75f4dba3e17b638ed92db68 (patch)
tree39d04e8f1d5b6025ee5e47a4842c1d92a6c265ae /gcc/c-family/c-attribs.cc
parent46f51bd73b77e572eb647eb56eddff663dd5e954 (diff)
downloadgcc-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/c-attribs.cc')
-rw-r--r--gcc/c-family/c-attribs.cc17
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