#858045 xcircuit: The File List Window can crash XCircuit

Package:
xcircuit
Source:
xcircuit
Description:
Draw circuit schematics or almost anything
Submitter:
Gonçalo Ribeiro
Date:
2018-11-24 15:27:06 UTC
Severity:
normal
#858045#5
Date:
2017-03-17 17:13:19 UTC
From:
To:
Dear Maintainer,

While following the tutorials on the XCircuit's official page I noticed an
action which makes it crash. The steps that result in the crash are as follows:

1. Open xcircuit
2. File -> Read XCircuit File (the "File List Window" screen will open)
3. Write in the text box "/usr/share/doc"
4. Press return
5. xcircuit crashes with the following output

    X Error of failed request:  BadAlloc (insufficient resources for operation)
      Major opcode of failed request:  53 (X_CreatePixmap)
      Serial number of failed request:  7021
      Current serial number in output stream:  8448

The numbers in the last two lines may change while reproducing the bug, but the
code 53 is always the same. The remaining options on the File List Window seem
to make no difference, the crash is consistent.

My suspicion for the cause of the bug might be due to the large number of items
in that directory.

    $ ls /usr/share/doc | wc -l
    3043

Almost all of them are folders, so all of them need to be displayed even with
the "filter" option turned on. This hypothesis is consistent with the following
experiment:

1. Repeat the steps above but using "/usr/bin" instead and with the "filter"
    option ticked. (For me, only the X11 folder is displayed and there is no
    crash.)
2. Untick the "filter" option
3. xcircuit crashes

    $ ls /usr/bin | wc -l
    3017


Thank you for your time,
Hope my hypothesis helps,
Gonçalo

PS: I was trying to navigate to the xcircuit examples folder when I found
the bug.

#858045#10
Date:
2018-11-24 15:26:16 UTC
From:
To:
Dear Maintainer, hello Gonçalo,
I tried to have a look at this issue, and could
reproduce it in a jessie and buster amd64 qemu VM.

As far as I see xcircuit tries to draw all files into one big pixmap.

    (gdb) list filelist.c:480
    477           pixheight = flfiles * FILECHARHEIGHT + 25;
    478           if (pixheight < textheight) pixheight = textheight;
    479
    480           flistpix = XCreatePixmap(dpy, areawin->window, textwidth, pixheight,
    481                DefaultDepthOfScreen(xcScreen(w)));
    (gdb) print pixheight
    $1 = 42039
    (gdb) print textheight
    $2 = 98
    (gdb) print flfiles
    $3 = 3001

Unfortunately, depending on the font size, we get then a height
of e.g. 42039, that is not allowed in the xserver:

    (gdb) list ProcCreatePixmap
    1392    int
    1393    ProcCreatePixmap(ClientPtr client)
    ...
    1415        if (stuff->width > 32767 || stuff->height > 32767) {
    1416            /* It is allowed to try and allocate a pixmap which is larger than
    1417             * 32767 in either dimension. However, all of the framebuffer code
    1418             * is buggy and does not reliably draw to such big pixmaps, basically
    1419             * because the Region data structure operates with signed shorts
    1420             * for the rectangles in it.
    1421             *
    1422             * Furthermore, several places in the X server computes the
    1423             * size in bytes of the pixmap and tries to store it in an
    1424             * integer. This integer can overflow and cause the allocated size
    1425             * to be much smaller.
    1426             *
    1427             * So, such big pixmaps are rejected here with a BadAlloc
    1428             */
    1429            return BadAlloc;
    1430        }


So a check like in filelist.c:478 could be added
to limit pixheight to 32767, or give a error message like
in the "(Invalid Directory)" case.

Kind regards,
Bernhard


Client:
    (gdb) bt
    #0  XCreatePixmap (dpy=0x561a0f1f4f60, d=8389047, width=339, height=42039, depth=24) at ../../src/CrPixmap.c:50
    #1  0x00007f67bfa7d020 in listfiles (w=0x561a0f846e00, okaystruct=0x561a0fa27f60, calldata=0x0) at filelist.c:480
    #2  0x00007f67bfa7d51a in newfilelist (w=0x561a0f846e00, okaystruct=0x561a0fa27f60) at filelist.c:547
    #3  0x00007f67bfafaec2 in xctk_fileselect (clientData=0x561a0fa27f60, eventPtr=0x7ffff0ef86f0) at tclxcircuit.c:9567
    #4  0x00007f67c19c7ff5 in Tk_HandleEvent (eventPtr=eventPtr@entry=0x7ffff0ef86f0) at ./unix/../generic/tkEvent.c:1352
    #5  0x00007f67c19bb3b0 in HandleEventGenerate (interp=interp@entry=0x561a0f46b6f0, mainWin=mainWin@entry=0x561a0f624180, objc=objc@entry=4, objv=objv@entry=0x561a0f486840) at ./unix/../generic/tkBind.c:3458
    #6  0x00007f67c19baaf1 in Tk_EventObjCmd (clientData=0x561a0f624180, interp=0x561a0f46b6f0, objc=6, objv=0x561a0f486830) at ./unix/../generic/tkBind.c:2413
    #7  0x00007f67c1608a96 in TclNRRunCallbacks (interp=interp@entry=0x561a0f46b6f0, result=0, rootPtr=0x0) at ./generic/tclBasic.c:4435
    #8  0x00007f67c1607ecf in Tcl_EvalObjv (interp=interp@entry=0x561a0f46b6f0, objc=objc@entry=6, objv=objv@entry=0x561a0f486830, flags=flags@entry=2097168) at ./generic/tclBasic.c:4165
    #9  0x00007f67c160964a in TclEvalEx (interp=0x561a0f46b6f0, script=0x7ffff0ef8af0 "event generate .filelist.listwin.win <ButtonPress> -button 2 ;  event generate .filelist.listwin.win <ButtonRelease> -button 2", numBytes=<optimized out>, flags=<optimized out>, line=line@entry=1, clNextOuter=clNextOuter@entry=0x0, outerScript=0x7ffff0ef8af0 "event generate .filelist.listwin.win <ButtonPress> -button 2 ;  event generate .filelist.listwin.win <ButtonRelease> -button 2") at ./generic/tclBasic.c:5304
    #10 0x00007f67c16090f3 in Tcl_EvalEx (interp=<optimized out>, script=<optimized out>, numBytes=<optimized out>, flags=<optimized out>) at ./generic/tclBasic.c:4969
    #11 0x00007f67c19b9705 in Tk_BindEvent (bindPtr=<optimized out>, eventPtr=eventPtr@entry=0x561a0f9f3aa0, tkwin=tkwin@entry=0x561a0f84c020, numObjects=<optimized out>, numObjects@entry=4, objectPtr=<optimized out>, objectPtr@entry=0x7ffff0ef8d20) at ./unix/../generic/tkBind.c:1505
    #12 0x00007f67c19bff4d in TkBindEventProc (winPtr=winPtr@entry=0x561a0f84c020, eventPtr=eventPtr@entry=0x561a0f9f3aa0) at ./unix/../generic/tkCmds.c:319
    #13 0x00007f67c19c8173 in Tk_HandleEvent (eventPtr=eventPtr@entry=0x561a0f9f3aa0) at ./unix/../generic/tkEvent.c:1374
    #14 0x00007f67c19c8920 in WindowEventProc (evPtr=evPtr@entry=0x561a0f9f3a90, flags=flags@entry=-3) at ./unix/../generic/tkEvent.c:1764
    #15 0x00007f67c16d0e17 in Tcl_ServiceEvent (flags=flags@entry=-3) at ./generic/tclNotify.c:670
    #16 0x00007f67c16d1066 in Tcl_DoOneEvent (flags=-3) at ./generic/tclNotify.c:903
    #17 0x00007f67c19c8d72 in Tk_MainLoop () at ./unix/../generic/tkEvent.c:2148
    #18 0x00007f67c19d741a in Tk_MainEx (argc=<optimized out>, argv=<optimized out>, appInitProc=0x561a0d485b30, interp=0x561a0f195f00) at ./unix/../generic/tkMain.c:390
    #19 0x0000561a0d485a0c in ?? ()
    #20 0x00007f67c07e7b17 in __libc_start_main (main=0x561a0d4859e0, argc=6, argv=0x7ffff0ef92a8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffff0ef9298) at ../csu/libc-start.c:310
    #21 0x0000561a0d485a4a in _start ()

XServer:
    (gdb) bt
    #0  ProcCreatePixmap (client=0x5599b8dce330) at ../../../../dix/dispatch.c:1415
    #1  0x00005599b7d2698e in Dispatch () at ../../../../dix/dispatch.c:478
    #2  0x00005599b7d2a936 in dix_main (argc=10, argv=0x7fffb806f7e8, envp=<optimized out>) at ../../../../dix/main.c:276
    #3  0x00007fc906b67b17 in __libc_start_main (main=0x5599b7d14650 <main>, argc=10, argv=0x7fffb806f7e8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffb806f7d8) at ../csu/libc-start.c:310
    #4  0x00005599b7d1468a in _start ()

#858045#13
Date:
2018-11-24 15:26:16 UTC
From:
To:
Dear Maintainer, hello Gonçalo,
I tried to have a look at this issue, and could
reproduce it in a jessie and buster amd64 qemu VM.

As far as I see xcircuit tries to draw all files into one big pixmap.

    (gdb) list filelist.c:480
    477           pixheight = flfiles * FILECHARHEIGHT + 25;
    478           if (pixheight < textheight) pixheight = textheight;
    479
    480           flistpix = XCreatePixmap(dpy, areawin->window, textwidth, pixheight,
    481                DefaultDepthOfScreen(xcScreen(w)));
    (gdb) print pixheight
    $1 = 42039
    (gdb) print textheight
    $2 = 98
    (gdb) print flfiles
    $3 = 3001

Unfortunately, depending on the font size, we get then a height
of e.g. 42039, that is not allowed in the xserver:

    (gdb) list ProcCreatePixmap
    1392    int
    1393    ProcCreatePixmap(ClientPtr client)
    ...
    1415        if (stuff->width > 32767 || stuff->height > 32767) {
    1416            /* It is allowed to try and allocate a pixmap which is larger than
    1417             * 32767 in either dimension. However, all of the framebuffer code
    1418             * is buggy and does not reliably draw to such big pixmaps, basically
    1419             * because the Region data structure operates with signed shorts
    1420             * for the rectangles in it.
    1421             *
    1422             * Furthermore, several places in the X server computes the
    1423             * size in bytes of the pixmap and tries to store it in an
    1424             * integer. This integer can overflow and cause the allocated size
    1425             * to be much smaller.
    1426             *
    1427             * So, such big pixmaps are rejected here with a BadAlloc
    1428             */
    1429            return BadAlloc;
    1430        }


So a check like in filelist.c:478 could be added
to limit pixheight to 32767, or give a error message like
in the "(Invalid Directory)" case.

Kind regards,
Bernhard


Client:
    (gdb) bt
    #0  XCreatePixmap (dpy=0x561a0f1f4f60, d=8389047, width=339, height=42039, depth=24) at ../../src/CrPixmap.c:50
    #1  0x00007f67bfa7d020 in listfiles (w=0x561a0f846e00, okaystruct=0x561a0fa27f60, calldata=0x0) at filelist.c:480
    #2  0x00007f67bfa7d51a in newfilelist (w=0x561a0f846e00, okaystruct=0x561a0fa27f60) at filelist.c:547
    #3  0x00007f67bfafaec2 in xctk_fileselect (clientData=0x561a0fa27f60, eventPtr=0x7ffff0ef86f0) at tclxcircuit.c:9567
    #4  0x00007f67c19c7ff5 in Tk_HandleEvent (eventPtr=eventPtr@entry=0x7ffff0ef86f0) at ./unix/../generic/tkEvent.c:1352
    #5  0x00007f67c19bb3b0 in HandleEventGenerate (interp=interp@entry=0x561a0f46b6f0, mainWin=mainWin@entry=0x561a0f624180, objc=objc@entry=4, objv=objv@entry=0x561a0f486840) at ./unix/../generic/tkBind.c:3458
    #6  0x00007f67c19baaf1 in Tk_EventObjCmd (clientData=0x561a0f624180, interp=0x561a0f46b6f0, objc=6, objv=0x561a0f486830) at ./unix/../generic/tkBind.c:2413
    #7  0x00007f67c1608a96 in TclNRRunCallbacks (interp=interp@entry=0x561a0f46b6f0, result=0, rootPtr=0x0) at ./generic/tclBasic.c:4435
    #8  0x00007f67c1607ecf in Tcl_EvalObjv (interp=interp@entry=0x561a0f46b6f0, objc=objc@entry=6, objv=objv@entry=0x561a0f486830, flags=flags@entry=2097168) at ./generic/tclBasic.c:4165
    #9  0x00007f67c160964a in TclEvalEx (interp=0x561a0f46b6f0, script=0x7ffff0ef8af0 "event generate .filelist.listwin.win <ButtonPress> -button 2 ;  event generate .filelist.listwin.win <ButtonRelease> -button 2", numBytes=<optimized out>, flags=<optimized out>, line=line@entry=1, clNextOuter=clNextOuter@entry=0x0, outerScript=0x7ffff0ef8af0 "event generate .filelist.listwin.win <ButtonPress> -button 2 ;  event generate .filelist.listwin.win <ButtonRelease> -button 2") at ./generic/tclBasic.c:5304
    #10 0x00007f67c16090f3 in Tcl_EvalEx (interp=<optimized out>, script=<optimized out>, numBytes=<optimized out>, flags=<optimized out>) at ./generic/tclBasic.c:4969
    #11 0x00007f67c19b9705 in Tk_BindEvent (bindPtr=<optimized out>, eventPtr=eventPtr@entry=0x561a0f9f3aa0, tkwin=tkwin@entry=0x561a0f84c020, numObjects=<optimized out>, numObjects@entry=4, objectPtr=<optimized out>, objectPtr@entry=0x7ffff0ef8d20) at ./unix/../generic/tkBind.c:1505
    #12 0x00007f67c19bff4d in TkBindEventProc (winPtr=winPtr@entry=0x561a0f84c020, eventPtr=eventPtr@entry=0x561a0f9f3aa0) at ./unix/../generic/tkCmds.c:319
    #13 0x00007f67c19c8173 in Tk_HandleEvent (eventPtr=eventPtr@entry=0x561a0f9f3aa0) at ./unix/../generic/tkEvent.c:1374
    #14 0x00007f67c19c8920 in WindowEventProc (evPtr=evPtr@entry=0x561a0f9f3a90, flags=flags@entry=-3) at ./unix/../generic/tkEvent.c:1764
    #15 0x00007f67c16d0e17 in Tcl_ServiceEvent (flags=flags@entry=-3) at ./generic/tclNotify.c:670
    #16 0x00007f67c16d1066 in Tcl_DoOneEvent (flags=-3) at ./generic/tclNotify.c:903
    #17 0x00007f67c19c8d72 in Tk_MainLoop () at ./unix/../generic/tkEvent.c:2148
    #18 0x00007f67c19d741a in Tk_MainEx (argc=<optimized out>, argv=<optimized out>, appInitProc=0x561a0d485b30, interp=0x561a0f195f00) at ./unix/../generic/tkMain.c:390
    #19 0x0000561a0d485a0c in ?? ()
    #20 0x00007f67c07e7b17 in __libc_start_main (main=0x561a0d4859e0, argc=6, argv=0x7ffff0ef92a8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffff0ef9298) at ../csu/libc-start.c:310
    #21 0x0000561a0d485a4a in _start ()

XServer:
    (gdb) bt
    #0  ProcCreatePixmap (client=0x5599b8dce330) at ../../../../dix/dispatch.c:1415
    #1  0x00005599b7d2698e in Dispatch () at ../../../../dix/dispatch.c:478
    #2  0x00005599b7d2a936 in dix_main (argc=10, argv=0x7fffb806f7e8, envp=<optimized out>) at ../../../../dix/main.c:276
    #3  0x00007fc906b67b17 in __libc_start_main (main=0x5599b7d14650 <main>, argc=10, argv=0x7fffb806f7e8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffb806f7d8) at ../csu/libc-start.c:310
    #4  0x00005599b7d1468a in _start ()