Exemplo n.º 1
0
enum type_cmp type_cmp(type *a, type *b, enum type_cmp_opts opts)
{
	const enum type_cmp cmp = type_cmp_r(a, b, opts);

	if(cmp == TYPE_CONVERTIBLE_EXPLICIT){
		/* try for implicit void * conversion */
		if(type_is_void_ptr(a) && type_is_ptr(b))
			return TYPE_CONVERTIBLE_IMPLICIT;

		if(type_is_void_ptr(b) && type_is_ptr(a))
			return TYPE_CONVERTIBLE_IMPLICIT;
	}

	return cmp;
}
Exemplo n.º 2
0
static void check_arg_voidness_and_nonnulls(
		expr *callexpr, symtable *stab,
		funcargs *args_from_decl, unsigned count_decl,
		expr **exprargs, char *sp)
{
	/* this block folds the args and type-checks */
	unsigned long nonnulls = 0;
	unsigned i;
	attribute *da;

	if((da = func_or_builtin_attr_present(callexpr, attr_nonnull)))
		nonnulls = da->bits.nonnull_args;

	for(i = 0; exprargs[i]; i++){
		expr *arg = FOLD_EXPR(exprargs[i], stab);
		char buf[64];

		ARG_BUF(buf, i, sp);

		if(fold_check_expr(arg, FOLD_CHK_NO_ST_UN, buf))
			continue;

		if(i < count_decl && (nonnulls & (1 << i))
		&& type_is_ptr(args_from_decl->arglist[i]->ref)
		&& expr_is_null_ptr(arg, NULL_STRICT_INT))
		{
			cc1_warn_at(&arg->where,
					attr_nonnull,
					"null passed where non-null required (arg %d)",
					i + 1);
		}
	}
}
Exemplo n.º 3
0
static type *is_val_ptr(const out_val *v)
{
	type *pointee = type_is_ptr(v->t);
	switch(v->type){
		case V_REG_SPILT:
			if(pointee){
				type *next = type_is_ptr(pointee);
				if(next)
					return next;
			}
			return NULL;

		default:
			return pointee ? v->t : NULL;
	}
}
Exemplo n.º 4
0
void sanitize_boundscheck(
    expr *elhs, expr *erhs,
    out_ctx *octx,
    const out_val *lhs, const out_val *rhs)
{
    decl *array_decl = NULL;
    type *array_ty;
    expr *expr_sz;
    consty sz;
    const out_val *val;

    if(!(cc1_sanitize & CC1_UBSAN))
        return;

    if(type_is_ptr(elhs->tree_type))
        array_decl = expr_to_declref(elhs, NULL), val = rhs;
    else if(type_is_ptr(erhs->tree_type))
        array_decl = expr_to_declref(erhs, NULL), val = lhs;

    if(!array_decl)
        return;

    if(!(array_ty = type_is(array_decl->ref, type_array)))
        return;

    expr_sz = array_ty->bits.array.size;
    if(!expr_sz)
        return;
    const_fold(expr_sz, &sz);

    if(sz.type != CONST_NUM)
        return;

    if(!K_INTEGRAL(sz.bits.num))
        return;

    /* force unsigned compare, which catches negative indexes */
    sanitize_assert_order(val, op_le, sz.bits.num.val.i, uintptr_ty(), octx, "bounds");
}
Exemplo n.º 5
0
int expr_is_null_ptr(expr *e, enum null_strictness ty)
{
	/* 6.3.2.3:
	 *
	 * An integer constant expression with the value 0, or such an expression
	 * cast to type void *, is called a null pointer constant
	 *
	 * NULL_STRICT_ANY_PTR is used for sentinel checks,
	 * i.e. any null type pointer
	 */

	int b = 0;

	/* void * always qualifies */
	if(type_is_primitive(type_is_ptr(e->tree_type), type_void))
		b = 1;
	else if(ty == NULL_STRICT_INT && type_is_integral(e->tree_type))
		b = 1;
	else if(ty == NULL_STRICT_ANY_PTR && type_is_ptr(e->tree_type))
		b = 1;

	return b && const_expr_and_zero(e);
}
Exemplo n.º 6
0
type *type_dereference_decay(type *const ty_ptr)
{
	type *const pointee = type_is_ptr(ty_ptr);
	assert(pointee);

	/* *(void (*)()) does nothing */
	if(type_is(pointee, type_func))
		return ty_ptr;

	/* decay never returns an array type - decay to pointer */
	if(type_is(pointee, type_array))
		return type_decay(pointee);

	return pointee;
}
Exemplo n.º 7
0
static int calc_ptr_step(type *t)
{
	type *tnext;
	/* we are calculating the sizeof *t */

	if(type_is_primitive(type_is_ptr(t), type_void))
		return type_primitive_size(type_void);

	if(type_is_primitive(t, type_unknown))
		return 1;

	tnext = type_next(t);
	if(type_is_vla(tnext, VLA_ANY_DIMENSION))
		return -1;
	return type_size(tnext, NULL);
}
Exemplo n.º 8
0
enum type_str_type
type_str_type(type *r)
{
	type *t = type_is_array(r);
	if(!t)
		t = type_is_ptr(r);
	t = type_is_primitive(t, type_unknown);
	switch(t ? t->bits.type->primitive : type_unknown){
		case type_schar:
		case type_nchar:
		case type_uchar:
			return type_str_char;

		case type_int:
			return type_str_wchar;

		default:
			return type_str_no;
	}
}
Exemplo n.º 9
0
static enum type_cmp type_cmp_r(
		type *const orig_a,
		type *const orig_b,
		enum type_cmp_opts opts)
{
	enum type_cmp ret;
	type *a, *b;
	int subchk = 1;

	if(!orig_a || !orig_b)
		return orig_a == orig_b ? TYPE_EQUAL : TYPE_NOT_EQUAL;

	a = type_skip_all(orig_a);
	b = type_skip_all(orig_b);

	/* array/func decay takes care of any array->ptr checks */
	if(a->type != b->type){
		/* allow _Bool <- pointer */
		if(type_is_primitive(a, type__Bool) && type_is_ptr(b))
			return TYPE_CONVERTIBLE_IMPLICIT;

		/* allow int <-> ptr (or block) */
		if((type_is_ptr_or_block(a) && type_is_integral(b))
		|| (type_is_ptr_or_block(b) && type_is_integral(a)))
		{
			return TYPE_CONVERTIBLE_EXPLICIT;
		}

		/* allow void <- anything */
		if(type_is_void(a))
			return TYPE_CONVERTIBLE_IMPLICIT;

		/* allow block <-> fnptr */
		if((type_is_fptr(a) && type_is(b, type_block))
		|| (type_is_fptr(b) && type_is(a, type_block)))
		{
			return TYPE_CONVERTIBLE_EXPLICIT;
		}

		return TYPE_NOT_EQUAL;
	}

	switch(a->type){
		case type_auto:
			ICE("__auto_type");

		case type_btype:
			subchk = 0;
			ret = btype_cmp(a->bits.type, b->bits.type);
			break;

		case type_array:
			if(a->bits.array.is_vla || b->bits.array.is_vla){
				/* fine, pretend they're equal even if different expressions */
				ret = TYPE_EQUAL_TYPEDEF;

			}else{
				const int a_has_sz = !!a->bits.array.size;
				const int b_has_sz = !!b->bits.array.size;

				if(a_has_sz && b_has_sz){
					integral_t av = const_fold_val_i(a->bits.array.size);
					integral_t bv = const_fold_val_i(b->bits.array.size);

					if(av != bv)
						return TYPE_NOT_EQUAL;
				}else if(a_has_sz != b_has_sz){
					if((opts & TYPE_CMP_ALLOW_TENATIVE_ARRAY) == 0)
						return TYPE_NOT_EQUAL;
				}
			}

			/* next */
			break;

		case type_block:
		case type_ptr:
			break;

		case type_cast:
		case type_tdef:
		case type_attr:
		case type_where:
			ICE("should've been skipped");

		case type_func:
			switch(funcargs_cmp(a->bits.func.args, b->bits.func.args)){
				case FUNCARGS_EXACT_EQUAL:
				case FUNCARGS_IMPLICIT_CONV:
					break;
				default:
					/* "void (int)" and "void (int, int)" aren't equal,
					 * but a cast can soon fix it */
					return TYPE_CONVERTIBLE_EXPLICIT;
			}
			break;
	}

	if(subchk)
		ret = type_cmp_r(a->ref, b->ref, opts);

	if(ret == TYPE_NOT_EQUAL
	&& a->type == type_func)
	{
		/* "int (int)" and "void (int)" aren't equal - but castable */
		ret = TYPE_CONVERTIBLE_EXPLICIT;
	}

	if(ret == TYPE_NOT_EQUAL
	&& a->type == type_ptr
	&& fopt_mode & FOPT_PLAN9_EXTENSIONS)
	{
		/* allow b to be an anonymous member of a, if pointers */
		struct_union_enum_st *a_sue = type_is_s_or_u(a),
		                     *b_sue = type_is_s_or_u(b);

		if(a_sue && b_sue /* already know they aren't equal */){
			/* b_sue has an a_sue,
			 * the implicit cast adjusts to return said a_sue */
			if(struct_union_member_find_sue(b_sue, a_sue))
				return TYPE_CONVERTIBLE_IMPLICIT;
		}
	}

	/* allow ptr <-> ptr */
	if(ret == TYPE_NOT_EQUAL && type_is_ptr(a) && type_is_ptr(b))
		ret = TYPE_CONVERTIBLE_EXPLICIT;

	/* char * and int * are explicitly conv.,
	 * even though char and int are implicit */
	if(ret == TYPE_CONVERTIBLE_IMPLICIT && a->type == type_ptr)
		ret = TYPE_CONVERTIBLE_EXPLICIT;

	if(a->type == type_ptr || a->type == type_block){
		switch(ret){
#define MAP(a, b) case a: ret = b; break
			MAP(TYPE_QUAL_ADD, TYPE_QUAL_POINTED_ADD);
			MAP(TYPE_QUAL_SUB, TYPE_QUAL_POINTED_SUB);
			MAP(TYPE_QUAL_POINTED_ADD, TYPE_QUAL_NESTED_CHANGE);
			MAP(TYPE_QUAL_POINTED_SUB, TYPE_QUAL_NESTED_CHANGE);
#undef MAP
			default:
				break;
		}
	}

	if(ret & TYPE_EQUAL_ANY){
		enum type_qualifier a_qual = type_qual(orig_a);
		enum type_qualifier b_qual = type_qual(orig_b);

		if(a_qual && b_qual){
			switch(type_qual_cmp(a_qual, b_qual)){
				case -1:
					/* a has more */
					ret = TYPE_QUAL_ADD;
					break;
				case 1:
					/* b has more */
					ret = TYPE_QUAL_SUB;
					break;
			}
		}else if(a_qual){
			ret = TYPE_QUAL_ADD;
		}else if(b_qual){
			ret = TYPE_QUAL_SUB;
		} /* else neither are casts */
	}

	if(ret == TYPE_EQUAL){
		int at = orig_a->type == type_tdef;
		int bt = orig_b->type == type_tdef;

		if(at != bt){
			/* one is a typedef */
			ret = TYPE_EQUAL_TYPEDEF;
		}else if(at){
			/* both typedefs */
			if(orig_a->bits.tdef.decl != orig_b->bits.tdef.decl){
				ret = TYPE_EQUAL_TYPEDEF;
			}
		}
		/* else no typedefs */
	}

	return ret;
}