[Patch][BZ 14594] Demangle function pointers before testing them
Jeff Law
law@redhat.com
Thu Sep 20 21:21:00 GMT 2012
If a gconv module's init function has an address that is the same as the
current pointer guard, then the gconv module's init function will not be
called.
The problem is find_module tests the *mangled* pointer against NULL; if
the pointer is non-NULL, then the initializer code is called.
With the mangling transformation being a simple xor against the pointer
guard, if the pointer guard has the same value as the function's real
address, then the mangled representation will have the value 0. Thus
resulting in the initializer function not getting called.
Inspection shows similar problems in gconv_db.c which I've fixed.
There's also an instance in btowc.c, but that merely gates an optimized
path and I didn't change that instance (I'm certainly willing to do so,
but with limited abilities to test I didn't want to change more than was
necessary to fix the correctness issues found.
Jeff
-------------- next part --------------
2012-09-20 Jeff Law <law@redhat.com>
[BZ #14594]
* iconv/gconv_cache.c (find_module): Demangle function pointer
before testing it.
* iconv/gconv_db.c (free_derivation): Likewise.
(__gconv_release_step, gen_steps, increment_counter): Likewise.
diff --git a/NEWS b/NEWS
index d9dfd20..d01c524 100644
--- a/NEWS
+++ b/NEWS
@@ -73,7 +73,7 @@ Version 2.16
14043, 14044, 14048, 14049, 14050, 14053, 14055, 14059, 14064, 14075,
14080, 14083, 14103, 14104, 14109, 14112, 14117, 14122, 14123, 14134,
14153, 14183, 14188, 14199, 14210, 14218, 14229, 14241, 14273, 14277,
- 14278,
+ 14278, 14594
* Support for the x32 ABI on x86-64 added. The x32 target is selected by
configuring glibc with:
diff --git a/iconv/gconv_cache.c b/iconv/gconv_cache.c
index 90b6cff..9e23708 100644
--- a/iconv/gconv_cache.c
+++ b/iconv/gconv_cache.c
@@ -1,5 +1,5 @@
/* Cache handling for iconv modules.
- Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005, 2007, 2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2001.
@@ -206,13 +206,13 @@ find_module (const char *directory, const char *filename,
result->__btowc_fct = NULL;
result->__data = NULL;
- /* Call the init function. */
- if (result->__init_fct != NULL)
- {
- __gconv_init_fct init_fct = result->__init_fct;
+ __gconv_init_fct init_fct = result->__init_fct;
#ifdef PTR_DEMANGLE
- PTR_DEMANGLE (init_fct);
+ PTR_DEMANGLE (init_fct);
#endif
+ /* Call the init function. */
+ if (init_fct != NULL)
+ {
status = DL_CALL_FCT (init_fct, (result));
#ifdef PTR_MANGLE
diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c
index 01015e8..7f91c7d 100644
--- a/iconv/gconv_db.c
+++ b/iconv/gconv_db.c
@@ -179,16 +179,17 @@ free_derivation (void *p)
size_t cnt;
for (cnt = 0; cnt < deriv->nsteps; ++cnt)
- if (deriv->steps[cnt].__counter > 0
- && deriv->steps[cnt].__end_fct != NULL)
+ if (deriv->steps[cnt].__counter > 0)
{
- assert (deriv->steps[cnt].__shlib_handle != NULL);
-
__gconv_end_fct end_fct = deriv->steps[cnt].__end_fct;
#ifdef PTR_DEMANGLE
PTR_DEMANGLE (end_fct);
#endif
- DL_CALL_FCT (end_fct, (&deriv->steps[cnt]));
+ if (end_fct != NULL)
+ {
+ assert (deriv->steps[cnt].__shlib_handle != NULL);
+ DL_CALL_FCT (end_fct, (&deriv->steps[cnt]));
+ }
}
/* Free the name strings. */
@@ -211,15 +212,15 @@ __gconv_release_step (struct __gconv_step *step)
/* Skip builtin modules; they are not reference counted. */
if (step->__shlib_handle != NULL && --step->__counter == 0)
{
+ __gconv_end_fct end_fct = step->__end_fct;
+#ifdef PTR_DEMANGLE
+ PTR_DEMANGLE (end_fct);
+#endif
/* Call the destructor. */
- if (step->__end_fct != NULL)
+ if (end_fct != NULL)
{
assert (step->__shlib_handle != NULL);
- __gconv_end_fct end_fct = step->__end_fct;
-#ifdef PTR_DEMANGLE
- PTR_DEMANGLE (end_fct);
-#endif
DL_CALL_FCT (end_fct, (step));
}
@@ -293,13 +294,13 @@ gen_steps (struct derivation_step *best, const char *toset,
/* Call the init function. */
__gconv_init_fct init_fct = result[step_cnt].__init_fct;
+# ifdef PTR_DEMANGLE
+ PTR_DEMANGLE (init_fct);
+# endif
if (init_fct != NULL)
{
assert (result[step_cnt].__shlib_handle != NULL);
-# ifdef PTR_DEMANGLE
- PTR_DEMANGLE (init_fct);
-# endif
status = DL_CALL_FCT (init_fct, (&result[step_cnt]));
if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
@@ -393,11 +394,11 @@ increment_counter (struct __gconv_step *steps, size_t nsteps)
/* Call the init function. */
__gconv_init_fct init_fct = step->__init_fct;
- if (init_fct != NULL)
- {
#ifdef PTR_DEMANGLE
- PTR_DEMANGLE (init_fct);
+ PTR_DEMANGLE (init_fct);
#endif
+ if (init_fct != NULL)
+ {
DL_CALL_FCT (init_fct, (step));
#ifdef PTR_MANGLE
More information about the Libc-alpha
mailing list