From UBS: ---8<--- In the Xlib code for the function parse_fontdata (in xc/libs/X11/omGeneric.c), error handling code which deals with failure of the get_rotate_fontname method does not correctly clean up its memory allocation. This causes later code in one of its callers (parse_vw) to attempt the memory cleanup again, resulting in a double-call to free() with the same memory address. This then corrupts the malloc data structures causing a segmentation fault shortly there after (or sometimes a hang in malloc_consolidate). In parse_fontdata, the snippet of code in question is: case C_VROTATE: if(is_found == True) { char *rotate_name; if((rotate_name = get_rotate_fontname(font_data->xlfd_name)) != NULL) { Xfree(font_data->xlfd_name); font_data->xlfd_name = rotate_name; return True; } Xfree(font_data->xlfd_name); return False; } break; In particular the last two lines of the failure scenario: Xfree(font_data->xlfd_name); return False; Now parse_vw method which calls parse_fontdata works thus: ret = parse_fontdata(oc, font_set, (FontData) vrotate, vrotate_num, name_list, count, C_VROTATE, NULL); if(ret == -1) { return (-1); } else if(ret == False) { CodeRange code_range; int num_cr; int sub_num = font_set->substitute_num; code_range = vrotate[0].code_range; /* ? */ num_cr = vrotate[0].num_cr; /* ? */ for(i = 0 ; i < vrotate_num ; i++) { if(vrotate[i].xlfd_name) Xfree(vrotate[i].xlfd_name); } Notice in particular the call if(vrotate[i].xlfd_name) Xfree(vrotate[i].xlfd_name); The member vortate[i].xlfd_name was already just freed when parse_fontdata failure. The patch to fix this crash is very simple. In parse_fontdata simply reset the pointer for xlfd_name to NULL having free'd it: Xfree(font_data->xlfd_name); font_data->xlfd_name = NULL; return False; A short test program to demonstrate the crash is as follows: #include <X11/Xos.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <stdio.h> #include <sys/types.h> #include <signal.h> #include <stdlib.h> #include <mcheck.h> int main(int argc, char** arbv) { Display *dpy; XEvent evt; char *base_name = "-dt-interface system-medium-r-normal-m*-*-*-*-*-*-*-*-*"; char **missing_charset; int missing_charsetn; char *def_str; XFontSet font_set; mtrace(); if (!(dpy = XOpenDisplay(NULL))) { fprintf(stderr, "Cannot open display"); return 0; } font_set = XCreateFontSet(dpy, base_name, &missing_charset, &missing_charsetn, &def_str); if (font_set) { XFreeFontSet(dpy, font_set); } XCloseDisplay(dpy); muntrace(); } Which can be compiled & run thus: gcc -o test -L/usr/X11R6/lib -lX11 test.c export MALLOC_TRACE=test.log ./test mtrace test.log | head -10 NB, the base_name member will have to be changed to refer to a font, which is both installed on your X server, and for which there is no rotated font data available. This particular example is reproducable by using ReflectionX 10.0 on WinXP to connect to a RHEL 3 server using XDMCP protocol & then running the test program. To the best of my knowledge it is not reproducable on XFree86 since the particular troublesome error cleanup code path is not executed. ---8<---
Created attachment 101634 [details] XFree86-4.3.0-omgeneric-double-free.patch Patch for the above. Probably needs to be applied to all the versions of XFree86 and derivates like X.org.
*** Bug 65265 has been marked as a duplicate of this bug. ***
I just spotted bug #65265 which is a duplicate and previously reported bug for this same problem. We'll review the patch for potential inclusion in all currently supported OS products for future updates (RHEL 2.1, RHEL 3, FC1, FC2). Thanks Bastien
I have filed this as http://freedesktop.org/bugzilla/show_bug.cgi?id=837
The bug is now fixed upstream, but I'll leave this bug open to track whether we want to merge into future updates.
Fix confirmed to be present in CVS: %changelog * Fri Sep 17 2004 Kristian Høgsberg <krh> 4.3.0-70.EL - Add patch for xlib double free (#127247).