This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/10296] New: QoI: ctype macros should trigger gcc -Wall warnings on 'char' argument


Consider this program:

#include <ctype.h>
int
main()
{
  char c = -2;
  unsigned char uc = -2;
  int table[2] = {0};
  c = isalpha (c);
  uc = isalpha (uc);
  c = table[c];
  uc = table[uc];
  return c + uc;
}

Depending on whether 'char' is a signed type, line 8 potentially violates the
standard, by passing an argument to isalpha that is outside the range of EOF or
unsigned char.  As a QoI point, glibc already handles this situation, by
allowing negative offsets (for all 'char' except -1, since that collides with
EOF) into the table lookup provided under the hood of the ctype macros.

But the QoI should be taken one step further.  It would be nice if <ctype.h>
were rewritten in such a manner as to warn the user that their program is not
portable.  For example, contrast compilation of the above program when using
newlib headers:
$ gcc -o foo -Wall foo.c
foo.c: In function `main':
foo.c:8: warning: subscript has type `char'
foo.c:10: warning: array subscript has type `char'

vs. when using glibc headers:
% gcc -o foo -Wall foo.c
foo.c: In function `main':
foo.c:10: warning: array subscript has type `char'

The difference? Look at the preprocessed results for newlib:
$ gcc -E foo.c | grep -C1 table
  unsigned char uc = -2;
  int table[2] = {0};
  c = ((__ctype_ptr__+1)[c]&(01|02));
  uc = ((__ctype_ptr__+1)[uc]&(01|02));
  c = table[c];
  uc = table[uc];
  return c + uc;

vs. for glibc (this from a machine with glibc 2.3.4, but even glibc 2.10 still
has a similar expansion)
% gcc -E foo.c | grep -C1 table
  unsigned char uc = -2;
  int table[2] = {0};
  c = ((*__ctype_b_loc ())[(int) ((c))] & (unsigned short int) _ISalpha);
  uc = ((*__ctype_b_loc ())[(int) ((uc))] & (unsigned short int) _ISalpha);
  c = table[c];
  uc = table[uc];
  return c + uc;

The difference is that newlib INTENTIONALLY used "c" as the array index, rather
than "(int) ((c))", since it is only by using a raw char as an index that you
can trigger the gcc -Wall warning.  All glibc has to do to help users find their
buggy uses of the ctype macros is to remove the spurious cast to int in the
__isctype macro of ctype/ctype.h.

-- 
           Summary: QoI: ctype macros should trigger gcc -Wall warnings on
                    'char' argument
           Product: glibc
           Version: 2.10
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: drepper at redhat dot com
        ReportedBy: ebb9 at byu dot net
                CC: glibc-bugs at sources dot redhat dot com


http://sourceware.org/bugzilla/show_bug.cgi?id=10296

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]