aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/builtin.c
diff options
Diffstat (limited to 'builtin.c')
-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 }},