* [PATCH] bogus cast in bio.c
@ 2005-09-09 15:53 viro
2005-09-09 16:18 ` Andreas Schwab
0 siblings, 1 reply; 8+ messages in thread
From: viro @ 2005-09-09 15:53 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel
<qualifier> void * is not the same as void <qualifier> *...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
----
diff -urN RC13-git8-base/fs/bio.c current/fs/bio.c
--- RC13-git8-base/fs/bio.c 2005-09-08 10:17:39.000000000 -0400
+++ current/fs/bio.c 2005-09-08 23:53:33.000000000 -0400
@@ -683,7 +683,7 @@
{
struct sg_iovec iov;
- iov.iov_base = (__user void *)uaddr;
+ iov.iov_base = (void __user *)uaddr;
iov.iov_len = len;
return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm);
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] bogus cast in bio.c
2005-09-09 15:53 [PATCH] bogus cast in bio.c viro
@ 2005-09-09 16:18 ` Andreas Schwab
2005-09-09 16:36 ` viro
0 siblings, 1 reply; 8+ messages in thread
From: Andreas Schwab @ 2005-09-09 16:18 UTC (permalink / raw)
To: viro; +Cc: Linus Torvalds, linux-kernel
viro@ZenIV.linux.org.uk writes:
> <qualifier> void * is not the same as void <qualifier> *...
IMHO it should.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] bogus cast in bio.c
2005-09-09 16:18 ` Andreas Schwab
@ 2005-09-09 16:36 ` viro
2005-09-09 17:29 ` [sparse fix] (was Re: [PATCH] bogus cast in bio.c) viro
0 siblings, 1 reply; 8+ messages in thread
From: viro @ 2005-09-09 16:36 UTC (permalink / raw)
To: Andreas Schwab; +Cc: Linus Torvalds, linux-kernel
On Fri, Sep 09, 2005 at 06:18:14PM +0200, Andreas Schwab wrote:
> viro@ZenIV.linux.org.uk writes:
>
> > <qualifier> void * is not the same as void <qualifier> *...
>
> IMHO it should.
... and indeed it should. My apologies - that's a combination of
sparse bug and me being very low on coffee...
FWIW, looks like we are losing address_space in the first form: with current
sparse we get
fs/bio.c:686:15: warning: incorrect type in assignment (different address spaces)
fs/bio.c:686:15: expected void [noderef] *iov_base<asn:1>
fs/bio.c:686:15: got void [noderef] *<noident>
from the first form (cast to __user void *). Lovely...
OK, I think I know what's going on there, will fix.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [sparse fix] (was Re: [PATCH] bogus cast in bio.c)
2005-09-09 16:36 ` viro
@ 2005-09-09 17:29 ` viro
2005-09-09 17:34 ` viro
2005-09-09 17:48 ` Linus Torvalds
0 siblings, 2 replies; 8+ messages in thread
From: viro @ 2005-09-09 17:29 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Andreas Schwab, linux-kernel
> fs/bio.c:686:15: warning: incorrect type in assignment (different address spaces)
> fs/bio.c:686:15: expected void [noderef] *iov_base<asn:1>
> fs/bio.c:686:15: got void [noderef] *<noident>
> from the first form (cast to __user void *). Lovely...
>
> OK, I think I know what's going on there, will fix.
What happens is actually pretty simple - we get address_space(1) handled
in declaration_specifiers(), which sets ctype->as to 1. Then we see
"void" and eventually get to
ctype->base_type = type;
}
check_modifiers(&token->pos, s, ctype->modifiers);
apply_ctype(token->pos, &thistype, ctype);
with thistype coming from lookup for "void". And that, of course, has
zero ->as. Now apply_ctype merrily buggers ctype->as and we have 0...
So AFAICS proper fix for sparse should be to check thistype->as to see
if it really has any intention to change ->as. ACK?
--- parse.c 2005-09-07 17:03:13.000000000 -0400
+++ parse.c.new 2005-09-09 13:25:01.000000000 -0400
@@ -636,7 +636,8 @@
ctype->alignment = thistype->alignment;
/* Address space */
- ctype->as = thistype->as;
+ if (thistype->as)
+ ctype->as = thistype->as;
}
static void check_modifiers(struct position *pos, struct symbol *s, unsigned long mod)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [sparse fix] (was Re: [PATCH] bogus cast in bio.c)
2005-09-09 17:29 ` [sparse fix] (was Re: [PATCH] bogus cast in bio.c) viro
@ 2005-09-09 17:34 ` viro
2005-09-09 17:48 ` Linus Torvalds
1 sibling, 0 replies; 8+ messages in thread
From: viro @ 2005-09-09 17:34 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Andreas Schwab, linux-kernel
On Fri, Sep 09, 2005 at 06:29:38PM +0100, viro@ZenIV.linux.org.uk wrote:
> > fs/bio.c:686:15: warning: incorrect type in assignment (different address spaces)
> > fs/bio.c:686:15: expected void [noderef] *iov_base<asn:1>
> > fs/bio.c:686:15: got void [noderef] *<noident>
> > from the first form (cast to __user void *). Lovely...
> >
> > OK, I think I know what's going on there, will fix.
>
> What happens is actually pretty simple - we get address_space(1) handled
> in declaration_specifiers(), which sets ctype->as to 1. Then we see
> "void" and eventually get to
> ctype->base_type = type;
> }
>
> check_modifiers(&token->pos, s, ctype->modifiers);
> apply_ctype(token->pos, &thistype, ctype);
> with thistype coming from lookup for "void". And that, of course, has
> zero ->as. Now apply_ctype merrily buggers ctype->as and we have 0...
>
> So AFAICS proper fix for sparse should be to check thistype->as to see
> if it really has any intention to change ->as. ACK?
PS: obvious testcase for that one:
#define X __attribute__((address_space(1)))
void X *p;
void X *q;
void foo(unsigned long n)
{
p = (void X *)n;
q = (X void *)n;
}
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [sparse fix] (was Re: [PATCH] bogus cast in bio.c)
2005-09-09 17:29 ` [sparse fix] (was Re: [PATCH] bogus cast in bio.c) viro
2005-09-09 17:34 ` viro
@ 2005-09-09 17:48 ` Linus Torvalds
2005-09-09 18:15 ` Linus Torvalds
1 sibling, 1 reply; 8+ messages in thread
From: Linus Torvalds @ 2005-09-09 17:48 UTC (permalink / raw)
To: viro; +Cc: Andreas Schwab, linux-kernel
On Fri, 9 Sep 2005 viro@ZenIV.linux.org.uk wrote:
>
> So AFAICS proper fix for sparse should be to check thistype->as to see
> if it really has any intention to change ->as. ACK?
Ack. Applied,
Linus
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [sparse fix] (was Re: [PATCH] bogus cast in bio.c)
2005-09-09 17:48 ` Linus Torvalds
@ 2005-09-09 18:15 ` Linus Torvalds
2005-09-09 20:10 ` viro
0 siblings, 1 reply; 8+ messages in thread
From: Linus Torvalds @ 2005-09-09 18:15 UTC (permalink / raw)
To: viro; +Cc: Andreas Schwab, linux-kernel
On Fri, 9 Sep 2005, Linus Torvalds wrote:
>
> Ack. Applied,
Btw, I also just committed the fix to not warn for
#if defined(TOKEN) && TOKEN > 1
when TOKEN is undefined and -Wundef is enabled. Implemented exactly the
way you suggested.
Linus
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [sparse fix] (was Re: [PATCH] bogus cast in bio.c)
2005-09-09 18:15 ` Linus Torvalds
@ 2005-09-09 20:10 ` viro
0 siblings, 0 replies; 8+ messages in thread
From: viro @ 2005-09-09 20:10 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Andreas Schwab, linux-kernel
On Fri, Sep 09, 2005 at 11:15:41AM -0700, Linus Torvalds wrote:
>
>
> On Fri, 9 Sep 2005, Linus Torvalds wrote:
> >
> > Ack. Applied,
>
> Btw, I also just committed the fix to not warn for
>
> #if defined(TOKEN) && TOKEN > 1
>
> when TOKEN is undefined and -Wundef is enabled. Implemented exactly the
> way you suggested.
Cool... Speaking of sparse patches:
* generates a warning when we cast _between_ address spaces (e.g. cast from
__user to __iomem).
* optional (on -Wcast-to-as) warning when casting _TO_ address space (e.g.
when normal pointer is cast to __iomem one - that caught a lot of crap in
drivers). casts from unsigned long are still OK, so's cast from 0, so's
__force cast, of course.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
----
diff --git a/evaluate.c b/evaluate.c
--- a/evaluate.c
+++ b/evaluate.c
@@ -2049,11 +2049,27 @@ static int get_as(struct symbol *sym)
return as;
}
+static void cast_to_as(struct expression *e, int as)
+{
+ struct expression *v = e->cast_expression;
+
+ if (!Wcast_to_address_space)
+ return;
+
+ /* cast from constant 0 to pointer is OK */
+ if (v->type == EXPR_VALUE && is_int_type(v->ctype) && !v->value)
+ return;
+
+ warning(e->pos, "cast adds address space to expression (<asn:%d>)", as);
+}
+
static struct symbol *evaluate_cast(struct expression *expr)
{
struct expression *target = expr->cast_expression;
struct symbol *ctype = examine_symbol_type(expr->cast_type);
- enum type type;
+ struct symbol *t1, *t2;
+ enum type type1, type2;
+ int as1, as2;
if (!target)
return NULL;
@@ -2092,51 +2108,54 @@ static struct symbol *evaluate_cast(stru
evaluate_expression(target);
degenerate(target);
+ t1 = ctype;
+ if (t1->type == SYM_NODE)
+ t1 = t1->ctype.base_type;
+ if (t1->type == SYM_ENUM)
+ t1 = t1->ctype.base_type;
+
/*
* You can always throw a value away by casting to
* "void" - that's an implicit "force". Note that
* the same is _not_ true of "void *".
*/
- if (ctype == &void_ctype)
+ if (t1 == &void_ctype)
goto out;
- type = ctype->type;
- if (type == SYM_NODE) {
- type = ctype->ctype.base_type->type;
- if (ctype->ctype.base_type == &void_ctype)
- goto out;
- }
- if (type == SYM_ARRAY || type == SYM_UNION || type == SYM_STRUCT)
+ type1 = t1->type;
+ if (type1 == SYM_ARRAY || type1 == SYM_UNION || type1 == SYM_STRUCT)
warning(expr->pos, "cast to non-scalar");
- if (!target->ctype) {
+ t2 = target->ctype;
+ if (!t2) {
warning(expr->pos, "cast from unknown type");
goto out;
}
+ if (t2->type == SYM_NODE)
+ t2 = t2->ctype.base_type;
+ if (t2->type == SYM_ENUM)
+ t2 = t2->ctype.base_type;
- type = target->ctype->type;
- if (type == SYM_NODE)
- type = target->ctype->ctype.base_type->type;
- if (type == SYM_ARRAY || type == SYM_UNION || type == SYM_STRUCT)
+ type2 = t2->type;
+ if (type2 == SYM_ARRAY || type2 == SYM_UNION || type2 == SYM_STRUCT)
warning(expr->pos, "cast from non-scalar");
- if (!get_as(ctype) && get_as(target->ctype) > 0)
- warning(expr->pos, "cast removes address space of expression");
-
- if (!(ctype->ctype.modifiers & MOD_FORCE)) {
- struct symbol *t1 = ctype, *t2 = target->ctype;
- if (t1->type == SYM_NODE)
- t1 = t1->ctype.base_type;
- if (t2->type == SYM_NODE)
- t2 = t2->ctype.base_type;
- if (t1 != t2) {
- if (t1->type == SYM_RESTRICT)
- warning(expr->pos, "cast to restricted type");
- if (t2->type == SYM_RESTRICT)
- warning(expr->pos, "cast from restricted type");
- }
+ if (!(ctype->ctype.modifiers & MOD_FORCE) && t1 != t2) {
+ if (t1->type == SYM_RESTRICT)
+ warning(expr->pos, "cast to restricted type");
+ if (t2->type == SYM_RESTRICT)
+ warning(expr->pos, "cast from restricted type");
}
+ as1 = get_as(ctype);
+ as2 = get_as(target->ctype);
+ if (!as1 && as2 > 0)
+ warning(expr->pos, "cast removes address space of expression");
+ if (as1 > 0 && as2 > 0 && as1 != as2)
+ warning(expr->pos, "cast between address spaces (<asn:%d>-><asn:%d>)", as2, as1);
+ if (as1 > 0 && !as2)
+ cast_to_as(expr, as1);
+
/*
* Casts of constant values are special: they
* can be NULL, and thus need to be simplified
diff --git a/lib.c b/lib.c
--- a/lib.c
+++ b/lib.c
@@ -170,6 +170,7 @@ int Wtypesign = 0;
int Wcontext = 0;
int Wundefined_preprocessor = 0;
int Wptr_subtraction_blows = 0;
+int Wcast_to_address_space = 0;
int Wtransparent_union = 1;
int preprocess_only;
char *include;
@@ -295,6 +296,7 @@ static const struct warning {
const char *name;
int *flag;
} warnings[] = {
+ { "cast-to-as", &Wcast_to_address_space },
{ "ptr-subtraction-blows", &Wptr_subtraction_blows },
{ "default-bitfield-sign", &Wdefault_bitfield_sign },
{ "undef", &Wundefined_preprocessor },
diff --git a/lib.h b/lib.h
--- a/lib.h
+++ b/lib.h
@@ -79,6 +79,7 @@ extern int Wdefault_bitfield_sign;
extern int Wundefined_preprocessor;
extern int Wbitwise, Wtypesign, Wcontext;
extern int Wtransparent_union;
+extern int Wcast_to_address_space;
extern void declare_builtin_functions(void);
extern void create_builtin_stream(void);
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2005-09-09 20:10 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-09 15:53 [PATCH] bogus cast in bio.c viro
2005-09-09 16:18 ` Andreas Schwab
2005-09-09 16:36 ` viro
2005-09-09 17:29 ` [sparse fix] (was Re: [PATCH] bogus cast in bio.c) viro
2005-09-09 17:34 ` viro
2005-09-09 17:48 ` Linus Torvalds
2005-09-09 18:15 ` Linus Torvalds
2005-09-09 20:10 ` viro
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.