public inbox for linux-rdma@vger.kernel.org
 help / color / mirror / Atom feed
From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
To: Leon Romanovsky <leon@kernel.org>
Cc: Bart Van Assche <bart.vanassche@sandisk.com>,
	Max Gurtovoy <maxg@mellanox.com>,
	matanb@mellanox.com, sagi@grimberg.me,
	linux-rdma@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH] IB/core: Fix different types mix in ib_device_cap_flags structure values
Date: Tue, 31 May 2016 13:39:56 -0600	[thread overview]
Message-ID: <20160531193956.GD21834@obsidianresearch.com> (raw)
In-Reply-To: <20160531185432.GF7477@leon.nu>

On Tue, May 31, 2016 at 09:54:32PM +0300, Leon Romanovsky wrote:

> > No, you quoted the relevant standard:
> > 
> > .. but shall be capable of representing the values of all the members
> >   of the enumeration. ..
> > 
> > Truncation is not allowed.
> 
> I'm not convinced that it talks about truncation.
> 
> From the same document:
> "The expression that defines the value of an enumeration constant shall
> be an integer constant expression that has a value representable as an
> int."

Hmm.

There are two things going on here.

The quote above is refereing to the type of the constants. In C99 the
type of the constants is not the type of the enum. (I did not know
that, what a goofy obscure thing. C++11 gets it right) It would appear
the constants are fixed at int by the standard.

However, gcc/clang both will upgrade the type of the constant values,
on a value by value basis, to something larger:

This illustrates the concept:

enum Foo
{
	FOO_VALUE1 = 1ULL,
	FOO_VALUE2 = (uint32_t)UINT32_MAX,
	FOO_VALUE3 = ((uint64_t)2) << 32,
	FOO_VALUE4 = 1<<31,
};

static void check_int(int *v)  { }
static void check_long(long *v)  { }
// Both work:
//static void check_ull(uint64_t *v)  { }
static void check_ull(enum Foo *v)  { }

int main(int argc,const char *argv[])
{
	check_int((__typeof__(FOO_VALUE1) *)0);
	check_long((__typeof__(FOO_VALUE2) *)0);
	check_ull((__typeof__(FOO_VALUE3) *)0);
	check_int((__typeof__(FOO_VALUE4) *)0);
}				  

The four constants have different types and the types are not
necessarily what you'd expect (eg FOO_VALUE3 has been promoted to a
64 bit signed long, FOO_VALUE1 has been demoted to an int)

So the enum is safe, but having different types of the values is
certainly unexpected.

I still think the actual bug is only 1<<31 I pointed out earlier:

enum Foo
{
	FOO_VALUE1 = 1,
	FOO_VALUE2 = ((uint64_t)2) << 32,
	FOO_VALUE3 = 1<<31,
};
uint64_t res = FOO_VALUE1 | FOO_VALUE2 | FOO_VALUE3;
printf("%lx\n",res);
==
ffffffff80000001

Which is clearly wrong. This is because signed int becomes sign
extended when converted to uint64_t, corrupting the upper bits.

Since adding the ULL's doesn't make the enum constants have uniform
type I would not bother with the churn.

Jason

  reply	other threads:[~2016-05-31 19:39 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-30 10:09 [PATCH] IB/core: Fix different types mix in ib_device_cap_flags structure values Max Gurtovoy
     [not found] ` <1464602994-21226-1-git-send-email-maxg-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2016-05-31 15:35   ` Bart Van Assche
2016-05-31 17:13     ` Jason Gunthorpe
     [not found]       ` <20160531171306.GA6618-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2016-05-31 17:30         ` Leon Romanovsky
     [not found]           ` <20160531173033.GC7477-2ukJVAZIZ/Y@public.gmane.org>
2016-05-31 18:05             ` Bart Van Assche
2016-05-31 18:12               ` Leon Romanovsky
     [not found]                 ` <20160531181223.GE7477-2ukJVAZIZ/Y@public.gmane.org>
2016-05-31 18:21                   ` Jason Gunthorpe
     [not found]                     ` <20160531182100.GC21834-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2016-05-31 18:54                       ` Leon Romanovsky
2016-05-31 19:39                         ` Jason Gunthorpe [this message]
2016-06-01 12:04                           ` Max Gurtovoy
     [not found]                             ` <574ECF44.3070003-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2016-06-01 15:35                               ` Sagi Grimberg
2016-05-31 18:43                   ` Bart Van Assche
2016-05-31 18:16               ` Jason Gunthorpe
2016-05-31 19:16   ` Robert LeBlanc
2016-05-31 15:36 ` Bart Van Assche
     [not found]   ` <4156c03f-4977-17eb-db64-6df775b6e592-XdAiOPVOjttBDgjK7y7TUQ@public.gmane.org>
2016-05-31 19:14     ` Max Gurtovoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160531193956.GD21834@obsidianresearch.com \
    --to=jgunthorpe@obsidianresearch.com \
    --cc=bart.vanassche@sandisk.com \
    --cc=leon@kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=matanb@mellanox.com \
    --cc=maxg@mellanox.com \
    --cc=sagi@grimberg.me \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox