[PATCH 1/3] util: change type of struct xlat.val to uint64_t

Jeff Mahoney jeffm at suse.com
Thu Mar 31 02:47:49 UTC 2016


On 3/30/16 9:48 PM, Dmitry V. Levin wrote:
> On Wed, Mar 30, 2016 at 09:19:25PM -0400, Jeff Mahoney wrote:
>> Some ioctls have flags fields that are 64-bit.  A 32-bit val means
>> these flags will never be matched or printed.

Thanks for the review.

TBH, I expected there to be some discussion on this one and I didn't
want to get too far into the weeds before having it.  I did enough work
to get the high value btrfs flags working on my x86_64 system.  I'm fine
continuing the work, but it wasn't the primary target of my time
investment. :)

> struct xlat is used for various kinds of thing all over the code,
> and this tiny change of type might have unforeseen consequences.
> [...]
>>  struct xlat {
>> -	unsigned int val;
>> +	uint64_t val;
>>  	const char *str;
>>  };
> [...]
>> -extern const char *xlookup(const struct xlat *, const unsigned int);
>> -extern const char *xlat_search(const struct xlat *, const size_t, const =
> unsigned int);
>> +extern const char *xlookup(const struct xlat *, const uint64_t);
>> +extern const char *xlat_search(const struct xlat *, const size_t, const =
> uint64_t);
> [...]
>> -extern void printxvals(const unsigned int, const char *, const struct xl=
> at *, ...);
>> +extern void printxvals(const uint64_t, const char *, const struct xlat *=
> , ...);
> [...]
>> -extern void addflags(const struct xlat *, int);
>> -extern int printflags(const struct xlat *, int, const char *);
>> -extern const char *sprintflags(const char *, const struct xlat *, int);
>> +extern void addflags(const struct xlat *, uint64_t);
>> +extern int printflags(const struct xlat *, uint64_t, const char *);
>> +extern const char *sprintflags(const char *, const struct xlat *, uint64=
> _t);
> 
> There is a potential sign extension bug in every place where a signed int
> is passed to any function "upgraded" from int/unsigned int to uint64_t.
> 
> Have you checked all these places?

No, I didn't. You're right, this could be a problem.  How about instead:

struct xlat.val is uint64_t.
Introduce *64 routines to handle those cases.
Change the signed int argument to unsigned for the existing prototypes.
Turn those routines into wrappers for the *64 versions so that no
unexpected signed extension happens.

>> @@ -132,16 +132,16 @@ xlookup(const struct xlat *xlat, const unsigned int=
>  val)
>>  static int
>>  xlat_bsearch_compare(const void *a, const void *b)
>>  {
>> -	const unsigned int val1 = (const unsigned long) a;
>> -	const unsigned int val2 = ((const struct xlat *) b)->val;
>> +	const uint64_t val1 = (const uint64_t) a;
> 
> This looks like a bug.
> 
>> +	const uint64_t val2 = ((const struct xlat *) b)->val;
>>  	return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0;
>>  }
>> =20
>>  const char *
>> -xlat_search(const struct xlat *xlat, const size_t nmemb, const unsigned =
> int val)
>> +xlat_search(const struct xlat *xlat, const size_t nmemb, const uint64_t =
> val)
>>  {
>>  	const struct xlat *e =
>> -		bsearch((const void*) (const unsigned long) val,
>> +		bsearch((const void*) val,
>>  			xlat, nmemb, sizeof(*xlat), xlat_bsearch_compare);
> 
> This also looks like a bug.  The only reason why it doesn't cause
> regressions on 32-bit systems is that the only user of xlat_search
> passes a value of type unsigned int.

Yeah, these are obviously wrong on !64bit.

-Jeff

-- 
Jeff Mahoney
SUSE Labs

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: OpenPGP digital signature
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20160330/c6826b7f/attachment.bin>


More information about the Strace-devel mailing list