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.
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 ()
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 ()