Nmap Development mailing list archives

Re: Nmap uses ctype macros improperly


From: David Fifield <david () bamsoftware com>
Date: Tue, 28 Jul 2009 09:00:52 -0600

On Tue, Jul 28, 2009 at 06:22:56PM +0400, Solar Designer wrote:
On Tue, Jul 28, 2009 at 05:23:05PM +0400, Solar Designer wrote:
unsigned char _bitmasks[0x200];
[...]
#define _LOWER 11
[...]
#define islower(c) \
    ((c) == EOF ? 0 : ((int)_bitmasks[((c) << 1) + (_LOWER >> 3)] & (1 << (_LOWER & 7))))

If "c" turns out to be an unsigned char instead of an int, this will
fail for values of "c" with the 8th bit set.

I was wrong.  "unsigned char" gets promoted to "unsigned int" in
arithmetic contexts such as the above.

I had just written a program to test it too. However I wasn't sure if it
worked only because of some behavior of GCC, or because some standard
requires it. I admit I don't know where to look for normative rules like
this; can you by chance point me to a standards document that defines
the arithmetic type promotion rule?

OK, I must admit I can't think of a reasonable implementation that would
suffer when the argument to ctype macros is of type "unsigned char"
rather than "int".  Yet I still think that strictly speaking an
implementation is free to misbehave in such a case.

Your point is well taken. The fact that both you and I weren't
immediately sure of what the above macro would do with an unsigned char
is an indication that relying on any specific behavior is dodgy. You've
convinced me; I'll ask Josh to add an extra (int) cast where
appropriate.

There are other problems with how the ctype functions are used. Well,
the only one I can think of now is in ncat/http.c, where they are used
to classify characters in HTTP. They should really be classified based
on the byte values defined in the HTTP standards, and not on whatever
the local character set happens to be. (For example, RFC 2616 defines
CTL, but there is no guarantee that is the same as the set defined by
iscntrl, even ignoring locale.) Also, that file refers to the CR and LF
bytes as '\r' and '\n', but it should use the literal values 0x0A and 0x0D.

David Fifield

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org


Current thread: