[PATCH] improve checks on usernames V3.
Matthias Andree
mandree at FreeBSD.org
Wed Aug 10 11:58:44 UTC 2011
Am 10.08.2011 13:24, schrieb Harald Becker:
> Hallo Denys!
>
>> On Tue, Aug 9, 2011 at 7:33 PM, Rich Felker <dalias at aerifal.cx> wrote:
>>> On Tue, Aug 09, 2011 at 09:37:58AM +0200, Denys Vlasenko wrote:
>>>> #define isalnum(a) bb_ascii_isalnum(a)
>>>> static ALWAYS_INLINE int bb_ascii_isalnum(unsigned char a)
>>>> {
>>>> unsigned char b = a - '0';
>>>> if (b <= 9)
>>>> return (b <= 9);
>>>> b = (a|0x20) - 'a';
>>>> return b <= 'z' - 'a';
>>>> }
>>> I'm scared to ask why this is written in such an obfuscated way rather
>>> than just
>>>
>>> return a-'0'<10U || (a|32)-'a'<26U;
>> Tried it. Bloatcheck:
>> [...]
>
> FYI: I tried it too ... test this version:
>
> return (unsigned char)(a-'0')<10U || (unsigned char)((a|32)-'a')<26U;
>
> ... may look obscure, but influences the way gcc produces code! May be
> you need to fiddle with type casting the other arguments in the
> expression :-(
Nothing in that is obscure, the answer is in the "integral promotion"
rules of C which is what required the extension from unsigned char to
unsigned int, hence the movz* commands in Denys's sample.
It pays to read the C and Unix standard, and you'll figure that the
simpler version causes implicit promotion to "unsigned int" - and note
that the C standard ctype.h signature demands "int interpreted as
unsigned char, or EOF". This sidesteps lots of the problems observed
here because no conversion happens inside the forcibly inlined
bb_ascii_alnum...
More information about the busybox
mailing list