bug-glibc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Bug in <ctype.h>


From: Stephan Wefing
Subject: Bug in <ctype.h>
Date: Thu, 14 Aug 2003 09:18:39 +0200

>Submitter-Id:  net
>Originator:    Stephan Wefing
>Organization:
none
>Confidential:  no
>Synopsis:      macros instead of functions in ctype.h
>Severity:      serious
>Priority:      medium
>Category:      libc
>Class:         sw-bug
>Release:       libc-2.2.5
>Environment:
        
Host type: i686-suse-linux-gnu
System: Linux kato 2.4.19-64GB-SMP #1 SMP Fri Sep 13 13:15:53 UTC 2002 i686 
unknown
Architecture: i686

Addons: db db2 linuxthreads noversion
Build CFLAGS: -O2 -mcpu=i686 -march=i686 -g
Build CC: gcc
Compiler version: 3.2
Kernel headers: 2.4.19
Symbol versioning: yes
Build static: yes
Build shared: yes
Build pic-default: no
Build profile: yes
Build omitfp: no
Build bounded: no
Build static-nss: no
Stdio: libio

>Description:
The character classification functions declared in ctype.h, e.g. isupper(int),
are implemented via macros instead of real function calls. The macros cast the
argument of the classification functions to type int. As a consequence, gcc
cannot detect argument type mismatches. As far as I can see, the C99 standard 
does not permit using macros instead of functions at this place.

This deviation from the standard has already been reported by Paul Eggert on
Thu, 5 Dec 2002, see http://mail.gnu.org/archive/html/bug-glibc. However, I
couldn't find a corresponding bug report in
http://bugs.gnu.org/cgi-bin/gnatsweb.pl.

>How-To-Repeat:

******************* conversion.c ********************************
01
02    #include <ctype.h>
03   
04    int main(void)
05    {
06       const char *ccp="0123";
07       int i=ccp;
08       if(isupper(ccp))
09          return 1;
10       return i;
11    }
12
*****************************************************************

kato wefing/c> gcc -std=c99 -o conversion conversion.c
conversion.c: In function `main':
conversion.c:7: warning: initialization makes integer from pointer without a 
cast

Note that there is no corresponding message for the type mismatch in line 8.
Preprocessing of conversion.c with "gcc -E conversion.c" gives the following
result:

# 1 "conversion.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "conversion.c"
# 1 "/usr/include/ctype.h" 1 3
# 26 "/usr/include/ctype.h" 3
# 1 "/usr/include/features.h" 1 3
# 283 "/usr/include/features.h" 3
# 1 "/usr/include/sys/cdefs.h" 1 3
# 284 "/usr/include/features.h" 2 3
# 312 "/usr/include/features.h" 3
# 1 "/usr/include/gnu/stubs.h" 1 3
# 313 "/usr/include/features.h" 2 3
# 27 "/usr/include/ctype.h" 2 3
# 1 "/usr/include/bits/types.h" 1 3
# 29 "/usr/include/bits/types.h" 3
# 1 "/usr/lib/gcc-lib/i486-suse-linux/3.2/include/stddef.h" 1 3
# 201 "/usr/lib/gcc-lib/i486-suse-linux/3.2/include/stddef.h" 3
typedef unsigned int size_t;
# 30 "/usr/include/bits/types.h" 2 3

typedef unsigned char __u_char;
typedef unsigned short __u_short;
typedef unsigned int __u_int;
typedef unsigned long __u_long;

__extension__ typedef unsigned long long int __u_quad_t;
__extension__ typedef long long int __quad_t;
# 49 "/usr/include/bits/types.h" 3
typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef signed short int __int16_t;
typedef unsigned short int __uint16_t;
typedef signed int __int32_t;
typedef unsigned int __uint32_t;

__extension__ typedef signed long long int __int64_t;
__extension__ typedef unsigned long long int __uint64_t;

typedef __quad_t *__qaddr_t;

typedef __u_quad_t __dev_t;
typedef __u_int __uid_t;
typedef __u_int __gid_t;
typedef __u_long __ino_t;
typedef __u_int __mode_t;
typedef __u_int __nlink_t;
typedef long int __off_t;
typedef __quad_t __loff_t;
typedef int __pid_t;
typedef int __ssize_t;
typedef __u_long __rlim_t;
typedef __u_quad_t __rlim64_t;
typedef __u_int __id_t;

typedef struct
  {
    int __val[2];
  } __fsid_t;

typedef int __daddr_t;
typedef char *__caddr_t;
typedef long int __time_t;
typedef unsigned int __useconds_t;
typedef long int __suseconds_t;
typedef long int __swblk_t;
typedef long int __clock_t;
typedef int __clockid_t;
typedef int __timer_t;
typedef int __key_t;
typedef unsigned short int __ipc_pid_t;
typedef long int __blksize_t;
typedef long int __blkcnt_t;
typedef __quad_t __blkcnt64_t;
typedef __u_long __fsblkcnt_t;
typedef __u_quad_t __fsblkcnt64_t;
typedef __u_long __fsfilcnt_t;
typedef __u_quad_t __fsfilcnt64_t;
typedef __u_quad_t __ino64_t;
typedef __loff_t __off64_t;
typedef long int __t_scalar_t;
typedef unsigned long int __t_uscalar_t;
typedef int __intptr_t;
typedef unsigned int __socklen_t;

# 1 "/usr/include/bits/pthreadtypes.h" 1 3
# 23 "/usr/include/bits/pthreadtypes.h" 3
# 1 "/usr/include/bits/sched.h" 1 3
# 68 "/usr/include/bits/sched.h" 3
struct __sched_param
  {
    int __sched_priority;
  };
# 24 "/usr/include/bits/pthreadtypes.h" 2 3
struct _pthread_fastlock
{
  long int __status;
  int __spinlock;
};
typedef struct _pthread_descr_struct *_pthread_descr;

typedef struct __pthread_attr_s
{
  int __detachstate;
  int __schedpolicy;
  struct __sched_param __schedparam;
  int __inheritsched;
  int __scope;
  size_t __guardsize;
  int __stackaddr_set;
  void *__stackaddr;
  size_t __stacksize;
} pthread_attr_t;

typedef struct
{
  struct _pthread_fastlock __c_lock;
  _pthread_descr __c_waiting;
} pthread_cond_t;

typedef struct
{
  int __dummy;
} pthread_condattr_t;

typedef unsigned int pthread_key_t;

typedef struct
{
  int __m_reserved;
  int __m_count;
  _pthread_descr __m_owner;
  int __m_kind;
  struct _pthread_fastlock __m_lock;
} pthread_mutex_t;

typedef struct
{
  int __mutexkind;
} pthread_mutexattr_t;

typedef int pthread_once_t;
# 140 "/usr/include/bits/pthreadtypes.h" 3
typedef unsigned long int pthread_t;
# 144 "/usr/include/bits/types.h" 2 3
# 28 "/usr/include/ctype.h" 2 3
# 40 "/usr/include/ctype.h" 3
# 1 "/usr/include/endian.h" 1 3
# 37 "/usr/include/endian.h" 3
# 1 "/usr/include/bits/endian.h" 1 3
# 38 "/usr/include/endian.h" 2 3
# 41 "/usr/include/ctype.h" 2 3

enum
{
  _ISupper = ((0) < 8 ? ((1 << (0)) << 8) : ((1 << (0)) >> 8)),
  _ISlower = ((1) < 8 ? ((1 << (1)) << 8) : ((1 << (1)) >> 8)),
  _ISalpha = ((2) < 8 ? ((1 << (2)) << 8) : ((1 << (2)) >> 8)),
  _ISdigit = ((3) < 8 ? ((1 << (3)) << 8) : ((1 << (3)) >> 8)),
  _ISxdigit = ((4) < 8 ? ((1 << (4)) << 8) : ((1 << (4)) >> 8)),
  _ISspace = ((5) < 8 ? ((1 << (5)) << 8) : ((1 << (5)) >> 8)),
  _ISprint = ((6) < 8 ? ((1 << (6)) << 8) : ((1 << (6)) >> 8)),
  _ISgraph = ((7) < 8 ? ((1 << (7)) << 8) : ((1 << (7)) >> 8)),
  _ISblank = ((8) < 8 ? ((1 << (8)) << 8) : ((1 << (8)) >> 8)),
  _IScntrl = ((9) < 8 ? ((1 << (9)) << 8) : ((1 << (9)) >> 8)),
  _ISpunct = ((10) < 8 ? ((1 << (10)) << 8) : ((1 << (10)) >> 8)),
  _ISalnum = ((11) < 8 ? ((1 << (11)) << 8) : ((1 << (11)) >> 8))
};
# 75 "/usr/include/ctype.h" 3
extern __const unsigned short int *__ctype_b;
extern __const __int32_t *__ctype_tolower;
extern __const __int32_t *__ctype_toupper;
# 91 "/usr/include/ctype.h" 3
extern int isalnum (int) ;
extern int isalpha (int) ;
extern int iscntrl (int) ;
extern int isdigit (int) ;
extern int islower (int) ;
extern int isgraph (int) ;
extern int isprint (int) ;
extern int ispunct (int) ;
extern int isspace (int) ;
extern int isupper (int) ;
extern int isxdigit (int) ;

extern int tolower (int __c) ;
extern int toupper (int __c) ;
extern int isascii (int __c) ;
extern int toascii (int __c) ;
extern int _toupper (int) ;
extern int _tolower (int) ;

# 276 "/usr/include/ctype.h" 3

# 2 "conversion.c" 2

int main(void)
{
   const char *ccp="0123";
   int i=ccp;
   if((__ctype_b[(int) ((ccp))] & (unsigned short int) _ISupper))
      return 1;
   return i;
}

Note that the function prototype provided for isupper() is useless with 
respect to error detection, since the original function call in line 8 has
been removed.

>Fix:
Perhaps inlining may be appropriate here.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]