diff --git a/builtin.c b/builtin.c index e4751445..d7e56b34 100644 --- a/builtin.c +++ b/builtin.c @@ -596,6 +596,49 @@ static struct symbol_op object_size_op = { .expand = expand_object_size, }; +#include +static int expand_strlen(struct expression *expr, int cost) +{ + struct expression *init, *arg = first_expression(expr->args); + unsigned long val = 0; + + if (!arg) + return UNSAFE; // ? ok + + switch (arg->type) { + case EXPR_STRING: + //todo// + break; + case EXPR_SYMBOL: + if (arg->symbol->ident) + goto not_literal; + + init = arg->symbol->initializer; + if (!init || init->type != EXPR_STRING) + goto not_literal; + + val = strlen(init->string->data); + break; + default: + goto not_literal; + break; + } + + expr->type = EXPR_VALUE; + expr->flags |= CEF_SET_ICE; + expr->value = val; + expr->taint = 0; + return 0; + +not_literal: + return UNSAFE; +} + + +static struct symbol_op strlen_op = { + .expand = expand_strlen, +}; + /* * Builtin functions */ @@ -775,7 +818,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, 1, { &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 }},