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

Bug#295015: xkbprint segfaults when



Package: xbase-clients
Version: 4.3.0.dfsg.1-10

When trying to print the keymap for my current xkb settings I was faced with
a segfault as I ran xkbprint. The problem is that if the XkbSymbols setting in
/etc/X11/XF86Config-4 is too long a sprintf() overruns a preallocated buffer
used when writing part of the generated Postscript to an output file.

hostname% /usr/bin/X11/xkbprint :0.0
zsh: segmentation fault  /usr/bin/X11/xkbprint :0.0

The fix that requires the least amount of modification, to my knowledge,
mainly consists of replacing sprintf() with asprintf(), as can be seen in
the patch below. As asprintf() itself allocates a buffer of suitable size
there is no longer any risk of overrunning a too small preallocated buffer.

Note that not just the one buffer that resulted in the segfault was fixed,
but all the similarly used buffers in the same function were also modified.
Additionally I have  appended my debugging session and test of the
modified xkbprint.

Please notify me if the patch is in any way inappropriate or if further
information is required.

/ Sebastian Rasmussen



diff -Nruw xfree86_4.3.0.dfsg-1.10/xc/programs/xkbprint/psgeom.c xfree86_4.3.0.dfsg-1.10.patched/xc/programs/xkbprint/psgeom.c --- xfree86_4.3.0.dfsg-1.10/xc/programs/xkbprint/psgeom.c 2001-07-25 17:05:25.000000000 +0200 +++ xfree86_4.3.0.dfsg-1.10.patched/xc/programs/xkbprint/psgeom.c 2005-02-13 00:25:25.000000000 +0100
@@ -807,18 +807,22 @@
           PSSetFont(out,state,FONT_LATIN1,14,False);
       }
       if (state->args->label==LABEL_SYMBOLS) {
-           char buf[40],*sName= NULL;
+           char *buf= NULL,*sName= NULL;
           Atom sAtom;

-           if (state->args->nLabelGroups==1)
-               sprintf(buf,"Group %d",state->args->baseLabelGroup+1);
-           else sprintf(buf,"Groups %d-%d",state->args->baseLabelGroup+1,
-               state->args->baseLabelGroup+state->args->nLabelGroups);
+           if (state->args->nLabelGroups==1) {
+ if (asprintf(&buf,"Group %d",state->args->baseLabelGroup+1)==-1)
+                   buf= NULL;
+           }
+ else if (asprintf(&buf,"Groups %d-%d",state->args->baseLabelGroup+1,
+               state->args->baseLabelGroup+state->args->nLabelGroups)==-1)
+               buf= NULL;
fprintf(out,"kbx kbdscalewidth 0 (%s) centeroffset pop add\n",buf);
           fprintf(out,"    kby kbdscaleheight add %d add\n",baseline);
           fprintf(out,"    moveto\n");
           fprintf(out,"1 -1 scale (%s) show 1 -1 scale\n",buf);
           baseline+= 16;
+           free(buf);

           if (xkb->names!=NULL)       sAtom= xkb->names->symbols;
           else                        sAtom= None;
@@ -827,12 +831,14 @@
           if (sName==NULL)
               sName= "(unknown)";

-           sprintf(buf,"Layout: %s",sName);
+           if (asprintf(&buf,"Layout: %s",sName)==-1)
+               buf= NULL;
fprintf(out,"kbx kbdscalewidth 0 (%s) centeroffset pop add\n",buf);
           fprintf(out,"    kby kbdscaleheight add %d add\n",baseline);
           fprintf(out,"    moveto\n");
           fprintf(out,"1 -1 scale (%s) show 1 -1 scale\n",buf);
           baseline+= 16;
+           free(buf);
       }
       if (name!=NULL) {
fprintf(out,"kbx kbdscalewidth 0 (%s) centeroffset pop add\n",name);
@@ -842,7 +848,7 @@
           baseline+= 16;
       }
       if (state->args->label==LABEL_KEYCODE) {
-           char buf[40],*sName= NULL;
+           char *buf= NULL,*sName= NULL;
           Atom sAtom;

           if (xkb->names!=NULL)       sAtom= xkb->names->keycodes;
@@ -852,12 +858,14 @@
           if (sName==NULL)
               sName= "(unknown)";

-           sprintf(buf,"Keycodes: %s",sName);
+           if (asprintf(&buf,"Keycodes: %s",sName)==-1)
+               buf= NULL;
fprintf(out,"kbx kbdscalewidth 0 (%s) centeroffset pop add\n",buf);
           fprintf(out,"    kby kbdscaleheight add %d add\n",baseline);
           fprintf(out,"    moveto\n");
           fprintf(out,"1 -1 scale (%s) show 1 -1 scale\n",buf);
           baseline+= 16;
+           free(buf);
       }
       if (state->args->copies>1) {
           for (p=1;p<state->args->copies;p++)
@@ -869,19 +877,23 @@
    }
    else {
       if ((!state->args->wantEPS)&&(state->args->label==LABEL_SYMBOLS)) {
-           char buf[40];
+           char *buf= NULL;
           baseline= 16;
           PSSetColor(out,state,state->black);
           PSSetFont(out,state,FONT_LATIN1,14,False);
-           if (state->args->nLabelGroups==1)
-               sprintf(buf,"Group %d",state->args->baseLabelGroup+1);
-           else sprintf(buf,"Groups %d-%d",state->args->baseLabelGroup+1,
-               state->args->baseLabelGroup+state->args->nLabelGroups+1);
+           if (state->args->nLabelGroups==1) {
+ if (asprintf(&buf,"Group %d",state->args->baseLabelGroup+1)==-1)
+                   buf= NULL;
+           }
+ else if (asprintf(&buf,"Groups %d-%d",state->args->baseLabelGroup+1, + state->args->baseLabelGroup+state->args->nLabelGroups+1)==-1)
+               buf= NULL;
fprintf(out,"kbx kbdscalewidth 0 (%s) centeroffset pop add\n",buf);
           fprintf(out,"    kby kbdscaleheight add %d add\n",baseline);
           fprintf(out,"    moveto\n");
           fprintf(out,"1 -1 scale (%s) show 1 -1 scale\n",buf);
           baseline+= 16;
+           free(buf);
       }
       fprintf(out,"restore\n");
       fprintf(out,"%% Done with keyboard %d\n",state->nPages+1);



hostname% /usr/bin/X11/xkbprint :0.0
zsh: segmentation fault  /usr/bin/X11/xkbprint :0.0
hostname% gdb --args /usr/bin/X11/xkbprint :0.0
(gdb) r
Starting program: /usr/X11R6/bin/xkbprint :0.0
(no debugging symbols found)

Program received signal SIGSEGV, Segmentation fault.
0x08002968 in ?? ()
(gdb)
hostname% file /usr/bin/X11/xkbprint
/usr/bin/X11/xkbprint: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.0, dynamically linked (uses shared libs), stripped
hostname% file ./xkbprint
./xkbprint: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.0, dynamically linked (uses shared libs), not stripped
hostname% gdb --args ./xkbprint :0.0
(gdb) r
Starting program: /tmp/xkbprint :0.0

Program received signal SIGSEGV, Segmentation fault.
0x4015fc2f in strlen () from /lib/libc.so.6
(gdb) bt
#0  0x4015fc2f in strlen () from /lib/libc.so.6
#1  0x401333a5 in vfprintf () from /lib/libc.so.6
#2  0x4013988f in fprintf () from /lib/libc.so.6
#3 0x0804cb2c in PSPageTrailer (out=0x80787f0, state=0xbffffb10) at psgeom.c:838 #4 0x0804fdd7 in GeometryToPostScript (out=0x80787f0, pResult=0xbffffb90, args=0x8071960) at psgeom.c:1785
#5  0x08051f12 in main (argc=2, argv=0xbffffc14) at xkbprint.c:740
(gdb) up
#1  0x401333a5 in vfprintf () from /lib/libc.so.6
(gdb) up
#2  0x4013988f in fprintf () from /lib/libc.so.6
(gdb) up
#3 0x0804cb2c in PSPageTrailer (out=0x80787f0, state=0xbffffb10) at psgeom.c:838 838 fprintf(out,"kbx kbdscalewidth 0 (%s) centeroffset pop add\n",name);
(gdb) print name
$1 = 0x8002968 <Address 0x8002968 out of bounds>
(gdb) break PSPageTrailer
Breakpoint 1 at 0x804c6d5: file psgeom.c, line 775.
(gdb) r

Starting program: /tmp/xkbprint :0.0

Breakpoint 1, PSPageTrailer (out=0x80787f0, state=0xbffffb10) at psgeom.c:775
775         xkb= state->xkb;
(gdb) watch name
Hardware watchpoint 2: name
[...]
(gdb) c
Continuing.
Hardware watchpoint 2: name

Old value = 0x8072968 ""
New value = 0x8002968 <Address 0x8002968 out of bounds>
0x4014bffe in vsprintf () from /lib/libc.so.6
(gdb) bt
#0  0x4014bffe in vsprintf () from /lib/libc.so.6
#1  0x4013994d in sprintf () from /lib/libc.so.6
#2 0x0804caa5 in PSPageTrailer (out=0x80787f0, state=0xbffffb10) at psgeom.c:830 #3 0x0804fdd7 in GeometryToPostScript (out=0x80787f0, pResult=0xbffffb90, args=0x8071960) at psgeom.c:1785
#4  0x08051f12 in main (argc=2, argv=0xbffffc14) at xkbprint.c:740
(gdb) up
#1  0x4013994d in sprintf () from /lib/libc.so.6
(gdb) up
#2 0x0804caa5 in PSPageTrailer (out=0x80787f0, state=0xbffffb10) at psgeom.c:830
830                 sprintf(buf,"Layout: %s",sName);
(gdb) print buf
$1 = "Layout: us(pc105)+altwin(meta_alt)+ct"
(gdb) reverse-search char.*buf
810                 char buf[40],*sName= NULL;
(gdb) q

[Applying patch and recompiling]

hostname% gdb --args ./xkbprint :0.0
(gdb) break psgeom.c:831
Breakpoint 1 at 0x804caca: file psgeom.c, line 831.
(gdb) r
Starting program: /tmp/xkbprint :0.0

Breakpoint 1, PSPageTrailer (out=0x8078830, state=0xbffffb10) at psgeom.c:831
831                 asprintf(&buf,"Layout: %s",sName);
(gdb) n
(gdb) print buf
$1 = 0x807b1c0 "Layout: us(pc105)+altwin(meta_alt)+ctrl(nocaps)+compose(rwin)+group(switch)"
(gdb) c
Continuing.

Program exited normally.
(gdb) q

_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today it's FREE! http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/




Reply to: