This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
__ctype_b_loc aliasing violation
- From: Adam Nemet <anemet at caviumnetworks dot com>
- To: libc-alpha at sourceware dot org
- Cc: jakub at redhat dot com
- Date: Thu, 6 Nov 2008 00:27:17 -0800
- Subject: __ctype_b_loc aliasing violation
The locale tests are failing on mips64octeon-linux-gnu (with config.sub from
GCC) because *__ctype_b_loc () can yield NULL.
The reason I believe is an aliasing violation in the implementation:
1 CTYPE_EXTERN_INLINE const uint16_t ** __attribute__ ((const))
2 __ctype_b_loc (void)
3 {
4 union
5 {
6 void **ptr;
7 const uint16_t **tablep;
8 } u;
9 u.ptr = __libc_tsd_address (CTYPE_B);
10 if (__builtin_expect (*u.tablep == NULL, 0))
11 *u.tablep = (const uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS) + 128;
12 return u.tablep;
13 }
After macro-expansion line 9 amounts to taking the address of a void *
variable. Therefore, on line 11, an object of effective type void * is
written as a uint16_t *. The union does not help here since that only allows
aliasing of pointers pointing to this.
Users of this function deference the return value so GCC forward-propagates
the address expression from line 9 into RHSs and removes the indirection.
This is the table pointer. Later PRE not seeing the dependency with the
actual initialization of the table pointer hoists reads from the table out of
a loop in _nl_normalize_codeset. Of course the table pointer is still NULL at
that point.
I think fixing this function should not be too hard but in theory callers of
__ctype_b_loc also access the table pointer as uint16_t * when its effective
type is void *. I don't quite see a way to fix that without changing the
interface of the function.
I am cc'ing Jakub because he looked at aliasing in the same function here:
http://sources.redhat.com/ml/libc-hacker/2003-07/msg00061.html
Adam