aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorDan Carpenter <dan.carpenter@linaro.org>2025-10-15 16:08:13 +0300
committerChris Li <sparse@chrisli.org>2025-10-16 21:52:33 -0700
commitfbdde3127b83e6d09e0ba808d7925dd84407f3c6 (patch)
tree602d0e365e38d1ed99ad775784728b9135b9c68c
parentdc9efe442b8949234a6599fdc94dc7221dd040e1 (diff)
downloadsparse-dev-master.tar.gz
builtin: implement __builtin_strlen() for constantsHEADmaster
People are adding compile time asserts to check whether strings are the expected length. In GCC and Clang strlen("foo") is expanded at compile time so this works, but in Sparse it triggers a "bad constant expression" warning. Implement expand_strlen() to handle string literals. Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org> Link: https://lore.kernel.org/all/CANiDSCsBAq3Yx4ybarUb_1NkQ-bvfXvWqb-DfqXatkiYJFZWiQ@mail.gmail.com/ Signed-off-by: Chris Li <sparse@chrisli.org>
-rw-r--r--builtin.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/builtin.c b/builtin.c
index 3a29c3ae..9149c43d 100644
--- a/builtin.c
+++ b/builtin.c
@@ -29,6 +29,7 @@
#include "expand.h"
#include "symbol.h"
#include "compat/bswap.h"
+#include "string.h"
#include <stdarg.h>
#define dyntype incomplete_ctype
@@ -596,6 +597,28 @@ static struct symbol_op object_size_op = {
.expand = expand_object_size,
};
+static int expand_strlen(struct expression *expr, int cost)
+{
+ struct expression *arg = first_expression(expr->args);
+
+ if (!arg)
+ return UNSAFE;
+ if (arg->type == EXPR_SYMBOL)
+ arg = arg->symbol->initializer;
+ if (!arg || arg->type != EXPR_STRING || !arg->string->length)
+ return UNSAFE;
+
+ expr->flags |= CEF_SET_ICE;
+ expr->type = EXPR_VALUE;
+ expr->value = strlen(arg->string->data);
+ expr->taint = 0;
+ return 0;
+}
+
+static struct symbol_op strlen_op = {
+ .expand = expand_strlen,
+};
+
/*
* Builtin functions
*/
@@ -775,7 +798,7 @@ static const struct builtin_fn builtins_common[] = {
{ "__builtin_strcpy", &string_ctype, 0, { &string_ctype, &const_string_ctype }},
{ "__builtin_strcspn", size_t_ctype, 0, { &const_string_ctype, &const_string_ctype }},
{ "__builtin_strdup", &string_ctype, 0, { &const_string_ctype }},
- { "__builtin_strlen", size_t_ctype, 0, { &const_string_ctype }},
+ { "__builtin_strlen", size_t_ctype, 0, { &const_string_ctype }, .op = &strlen_op},
{ "__builtin_strncasecmp", &int_ctype, 0, { &const_string_ctype, &const_string_ctype, size_t_ctype }},
{ "__builtin_strncat", &string_ctype, 0, { &string_ctype, &const_string_ctype, size_t_ctype }},
{ "__builtin_strncmp", &int_ctype, 0, { &const_string_ctype, &const_string_ctype, size_t_ctype }},