Skip to content

Commit

Permalink
Merge branch 'objsize'
Browse files Browse the repository at this point in the history
* expand __builtin_object_size()
  • Loading branch information
lucvoo committed Feb 25, 2021
2 parents 3d61735 + eb55532 commit eaceeaf
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 1 deletion.
73 changes: 72 additions & 1 deletion builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,77 @@ static struct symbol_op atomic_op = {
};


///
// expand __builtin_object_size()
//
// :note: type 1 and type 3 are not supported because the
// needed information isn't available after evaluation.
static int expand_object_size(struct expression *expr, int cost)
{
struct expression *arg = first_expression(expr->args);
int type = get_expression_value_silent(ptr_list_nth(expr->args, 1));
unsigned long val = -1, off = 0;

while (arg) {
switch (arg->type) {
case EXPR_IMPLIED_CAST:
case EXPR_CAST:
// ignore those
arg = arg->cast_expression;
continue;
case EXPR_BINOP:
// a constant add is (maybe) an offset
if (!arg->right || arg->op != '+' || arg->right->type != EXPR_VALUE)
break;
off += arg->right->value;
arg = arg->left;
continue;
case EXPR_PREOP:
// a deref is just intermediate variable
// and so the offset needs to be zeroed.
if (arg->op == '*') {
arg = arg->unop;
off = 0;
switch (arg->type) {
case EXPR_SYMBOL:
arg = arg->symbol->initializer;
continue;
default:
break;
}
}
break;
case EXPR_SYMBOL:
// the symbol we're looking after
val = bits_to_bytes(arg->symbol->bit_size);
break;
case EXPR_CALL:
// use alloc_size() attribute but only after linearization.
return UNSAFE;
default:
break;
}
break;
}

if (val == -1)
val = (type & 2) ? 0 : val;
else if (type & 1)
return UNSAFE;
else
val -= off;

expr->flags |= CEF_SET_ICE;
expr->type = EXPR_VALUE;
expr->value = val;
expr->taint = 0;
return 0;
}

static struct symbol_op object_size_op = {
.expand = expand_object_size,
};

/*
* Builtin functions
*/
Expand Down Expand Up @@ -598,7 +669,7 @@ static const struct builtin_fn builtins_common[] = {
{ "__builtin_nan", &double_ctype, 0, { &const_string_ctype }},
{ "__builtin_nanf", &float_ctype, 0, { &const_string_ctype }},
{ "__builtin_nanl", &ldouble_ctype, 0, { &const_string_ctype }},
{ "__builtin_object_size", size_t_ctype, 0, { &const_ptr_ctype, &int_ctype }},
{ "__builtin_object_size", size_t_ctype, 0, { &const_ptr_ctype, &int_ctype }, .op = &object_size_op},
{ "__builtin_parity", &int_ctype, 0, { &uint_ctype }, .op = &parity_op },
{ "__builtin_parityl", &int_ctype, 0, { &ulong_ctype }, .op = &parity_op },
{ "__builtin_parityll", &int_ctype, 0, { &ullong_ctype }, .op = &parity_op },
Expand Down
4 changes: 4 additions & 0 deletions ptrlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ extern void __free_ptr_list(struct ptr_list **);
__free_ptr_list((struct ptr_list **)(list)); \
} while (0)

#define ptr_list_nth(lst, nth) ({ \
struct ptr_list* head = (struct ptr_list*)(lst); \
(__typeof__((lst)->list[0])) ptr_list_nth_entry(head, nth);\
})

////////////////////////////////////////////////////////////////////////
// API
Expand Down
22 changes: 22 additions & 0 deletions validation/builtin-objsize-dyn.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
void *alloc(unsigned long)__attribute__((alloc_size(1)));

_Bool sta(void)
{
void *ptr = alloc(4);
return __builtin_object_size(ptr, 0) == 4;
}

_Bool dyn(unsigned long n)
{
void *ptr = alloc(n);
return __builtin_object_size(ptr, 0) == n;
}

/*
* check-name: builtin-objsize-dyn
* check-command: test-linearize -Wno-decl $file
* check-known-to-fail
*
* check-output-ignore
* check-output-returns: 1
*/
25 changes: 25 additions & 0 deletions validation/builtin-objsize0.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#define bos(O, T) __builtin_object_size(O, T)

struct s {
char arr[8];
__INT32_TYPE__ i;
__INT32_TYPE__ padding;
};

static struct s s;
static char *p = &s.arr[1];
static int *q = &s.i;

int obj_int0(void) { return bos(&s.i, 0) == 8; }
int obj_arr0(void) { return bos(&s.arr[1], 0) == 15; }

int ptr_int(struct s *p) { return bos(&p->i, 0) == -1; }
int ptr_arr(struct s *p) { return bos(&p->arr[1], 0) == -1; }

/*
* check-name: builtin-objsize0
* check-command: test-linearize -Wno-decl $file
*
* check-output-ignore
* check-output-returns: 1
*/
21 changes: 21 additions & 0 deletions validation/builtin-objsize1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#define bos(O, T) __builtin_object_size(O, T)

struct s {
char arr[8];
__INT32_TYPE__ i;
__INT32_TYPE__ padding;
};

static struct s s;

int obj_int1(void) { return bos(&s.i, 1) == 4; }
int obj_arr1(void) { return bos(&s.arr[1], 1) == 7; }

/*
* check-name: builtin-objsize1
* check-command: test-linearize -Wno-decl $file
* check-known-to-fail
*
* check-output-ignore
* check-output-returns: 1
*/

0 comments on commit eaceeaf

Please sign in to comment.