Control: retitle -1 screen: memory corruption when $TERM's total termcap length exceeds buffer => segfault or malloc SIGABRT Control: found -1 4.9.0-4 Control: found -1 4.9.1-1 Control: tag -1 = patch
Installed screen again, hit a segfault, reportbug said I have this open already. Repro on bookworm/amd64 and sid/x32. This time with some more interesting gubbins, hopefully, because strace on bookworm ends with -- >8 -- 3234294 ioctl(1, TCGETS, 0x7fff4f414180) = -1 ENOTTY (Inappropriate ioctl for device) 3234294 access("/etc/terminfo/s/st-256color", R_OK) = 0 3234294 getuid() = 1000 3234294 setfsuid(1000) = 1000 3234294 getgid() = 100 3234294 setfsgid(100) = 100 3234294 openat(AT_FDCWD, "/etc/terminfo/s/st-256color", O_RDONLY) = 5 3234294 geteuid() = 1000 3234294 setfsuid(1000) = 1000 3234294 getegid() = 100 3234294 setfsgid(100) = 100 3234294 newfstatat(5, "", {st_mode=S_IFREG|0644, st_size=2565, ...}, AT_EMPTY_PATH) = 0 3234294 read(5, "\32\1(\0\35\0\17\0i\1W\6st-256color| simplet"..., 30720) = 2565 3234294 read(5, "", 27648) = 0 3234294 close(5) = 0 3234294 ioctl(2, TCGETS, 0x7fff4f414180) = -1 ENOTTY (Inappropriate ioctl for device) 3234294 ioctl(2, TCGETS, 0x7fff4f414110) = -1 ENOTTY (Inappropriate ioctl for device) 3234294 writev(2, [{iov_base="corrupted size vs. prev_size", iov_len=28}, {iov_base="\n", iov_len=1}], 2) = 29 3234294 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7feaabb5c000 3234294 rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0 3234294 gettid() = 3234294 3234294 getpid() = 3234294 3234294 tgkill(3234294, 3234294, SIGABRT) = 0 3234294 --- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=3234294, si_uid=1000} --- 3234294 +++ killed by SIGABRT +++ -- >8 -- for the child and then the top-level process hangs (well, it loops in pause() with ^C ignored; ^Z/^\ work normally). Pretty sure this is a malloc sanity-check abort message? On sid I just get "[screen caught signal 11. (core dumped)]" and no coredump. No valgrind for x32 so whatever. On bookworm for valgrind screen ls I get: -- >8 -- ==3274260== Memcheck, a memory error detector ==3274260== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==3274260== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info ==3274260== Command: screen ls ==3274260== ==3274433== Invalid write of size 1 ==3274433== at 0x48468E4: strcpy (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x487E600: UnknownInlinedFun (string_fortified.h:79) ==3274433== by 0x487E600: tgetstr_sp (lib_termcap.c:380) ==3274433== by 0x135FDA: e_tgetstr (termcap.c:1505) ==3274433== by 0x135FDA: InitTermcap (termcap.c:157) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23b66 is 0 bytes after a block of size 1,030 alloc'd ==3274433== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x135E29: InitTermcap (termcap.c:136) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== ==3274433== Invalid write of size 1 ==3274433== at 0x48468F6: strcpy (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x487E600: UnknownInlinedFun (string_fortified.h:79) ==3274433== by 0x487E600: tgetstr_sp (lib_termcap.c:380) ==3274433== by 0x135FDA: e_tgetstr (termcap.c:1505) ==3274433== by 0x135FDA: InitTermcap (termcap.c:157) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23b68 is 2 bytes after a block of size 1,030 alloc'd ==3274433== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x135E29: InitTermcap (termcap.c:136) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== ==3274433== Invalid read of size 1 ==3274433== at 0x48467F4: __strlen_sse2 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x487E60C: tgetstr_sp (lib_termcap.c:382) ==3274433== by 0x135FDA: e_tgetstr (termcap.c:1505) ==3274433== by 0x135FDA: InitTermcap (termcap.c:157) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23b66 is 0 bytes after a block of size 1,030 alloc'd ==3274433== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x135E29: InitTermcap (termcap.c:136) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== ==3274433== Invalid read of size 1 ==3274433== at 0x48467E2: __strlen_sse2 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x487E60C: tgetstr_sp (lib_termcap.c:382) ==3274433== by 0x135FDA: e_tgetstr (termcap.c:1505) ==3274433== by 0x135FDA: InitTermcap (termcap.c:157) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23b69 is 3 bytes after a block of size 1,030 alloc'd ==3274433== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x135E29: InitTermcap (termcap.c:136) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== ==3274433== Invalid read of size 1 ==3274433== at 0x135E9F: InitTermcap (termcap.c:159) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23b69 is 3 bytes after a block of size 1,030 alloc'd ==3274433== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x135E29: InitTermcap (termcap.c:136) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== ==3274433== Invalid read of size 1 ==3274433== at 0x136912: InitTermcap (termcap.c:469) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23ba5 is 11 bytes before a block of size 7,952 alloc'd ==3274433== at 0x48455EF: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x4879967: _nc_build_names (comp_captab.c:3285) ==3274433== by 0x487A10A: _nc_find_type_entry (comp_hash.c:104) ==3274433== by 0x487E453: tgetnum_sp (lib_termcap.c:300) ==3274433== by 0x135FFF: e_tgetnum (termcap.c:1541) ==3274433== by 0x135FFF: InitTermcap (termcap.c:154) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== ==3274433== Invalid read of size 1 ==3274433== at 0x48467F4: __strlen_sse2 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x133A18: remap (termcap.c:528) ==3274433== by 0x13695E: InitTermcap (termcap.c:478) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23b66 is 0 bytes after a block of size 1,030 alloc'd ==3274433== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x135E29: InitTermcap (termcap.c:136) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== ==3274433== Invalid read of size 1 ==3274433== at 0x13313C: findseq_ge (termcap.c:632) ==3274433== by 0x133CE2: addmapseq (termcap.c:687) ==3274433== by 0x133CE2: remap (termcap.c:562) ==3274433== by 0x13695E: InitTermcap (termcap.c:478) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23b66 is 0 bytes after a block of size 1,030 alloc'd ==3274433== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x135E29: InitTermcap (termcap.c:136) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== ==3274433== Invalid read of size 1 ==3274433== at 0x4847A1D: memcpy@GLIBC_2.2.5 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x133D94: UnknownInlinedFun (strings_fortified.h:25) ==3274433== by 0x133D94: addmapseq (termcap.c:710) ==3274433== by 0x133D94: remap (termcap.c:562) ==3274433== by 0x13695E: InitTermcap (termcap.c:478) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23b66 is 0 bytes after a block of size 1,030 alloc'd ==3274433== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x135E29: InitTermcap (termcap.c:136) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== ==3274433== Invalid read of size 1 ==3274433== at 0x4847A10: memcpy@GLIBC_2.2.5 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x133D94: UnknownInlinedFun (strings_fortified.h:25) ==3274433== by 0x133D94: addmapseq (termcap.c:710) ==3274433== by 0x133D94: remap (termcap.c:562) ==3274433== by 0x13695E: InitTermcap (termcap.c:478) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23b67 is 1 bytes after a block of size 1,030 alloc'd ==3274433== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x135E29: InitTermcap (termcap.c:136) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== ==3274433== Invalid read of size 1 ==3274433== at 0x133ED9: addmapseq (termcap.c:733) ==3274433== by 0x133ED9: remap (termcap.c:562) ==3274433== by 0x13695E: InitTermcap (termcap.c:478) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23b66 is 0 bytes after a block of size 1,030 alloc'd ==3274433== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x135E29: InitTermcap (termcap.c:136) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== ==3274433== Invalid read of size 1 ==3274433== at 0x48467E2: __strlen_sse2 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x133A18: remap (termcap.c:528) ==3274433== by 0x13695E: InitTermcap (termcap.c:478) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== Address 0x4b23b69 is 3 bytes after a block of size 1,030 alloc'd ==3274433== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x135E29: InitTermcap (termcap.c:136) ==3274433== by 0x112B28: main (screen.c:1390) ==3274433== valgrind: m_mallocfree.c:303 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed. valgrind: Heap block lo/hi size mismatch: lo = 1104, hi = 9093149294164390459. This is probably caused by your program erroneously writing past the end of a heap block and corrupting heap metadata. If you fix any invalid writes reported by Memcheck, this assertion failure will probably go away. Please try that before reporting this as a bug. host stacktrace: ==3274433== at 0x580429AA: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux) ==3274433== by 0x58042AC7: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux) ==3274433== by 0x58042C57: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux) ==3274433== by 0x5804C708: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux) ==3274433== by 0x5803B31A: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux) ==3274433== by 0x58039A1E: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux) ==3274433== by 0x5803E1F5: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux) ==3274433== by 0x58038CF8: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux) ==3274433== by 0x5800F063: ??? (in /usr/libexec/valgrind/memcheck-amd64-linux) ==3274433== by 0x1002F02807: ??? ==3274433== by 0x1002DB5F2F: ??? ==3274433== by 0x1002DB5F17: ??? ==3274433== by 0x1002DB5F2F: ??? ==3274433== by 0x1C0F: ??? ==3274433== by 0x100200839F: ??? sched status: running_tid=1 Thread 1: status = VgTs_Runnable (lwpid 3274433) ==3274433== at 0x48478F1: memcpy@GLIBC_2.2.5 (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==3274433== by 0x133D94: UnknownInlinedFun (strings_fortified.h:25) ==3274433== by 0x133D94: addmapseq (termcap.c:710) ==3274433== by 0x133D94: remap (termcap.c:562) ==3274433== by 0x13695E: InitTermcap (termcap.c:478) ==3274433== by 0x112B28: main (screen.c:1390) client stack range: [0x1FFEFE5000 0x1FFF000FFF] client SP: 0x1FFEFFEA08 valgrind stack range: [0x1002CB6000 0x1002DB5FFF] top usage: 19208 of 1048576 -- >8 -- which confirms memory corruption. Despite the suggestive name, termcap.c appears to be from screen: 136 if ((D_tentry = (char *)malloc(TERMCAP_BUFSIZE + (extra_incap ? strlen(extra_incap) + 1 : 0))) == 0) ... 145 tp = D_tentry; 146 for (i = 0; i < T_N; i++) { 148 switch(term[i].type) { 156 case T_STR: 157 D_tcs[i].str = e_tgetstr(term[i].tcname, &tp); 1497 static char * e_tgetstr(cap, tepp) char *cap; char **tepp; { 1502 char *tep; 1503 if ((tep = findcap(cap, tepp, 0))) 1504 return (*tep == '@') ? 0 : tep; 1505 return tgetstr(cap, tepp); tgetstr(3) doesn't seem to say what the size /should/ be. lib_termcap.c 342 NCURSES_SP_NAME(tgetstr) (NCURSES_SP_DCLx const char *id, char **area) 378 if (area != 0 379 && *area != 0) { 380 _nc_STRCPY(*area, result, 1024); 381 result = *area; 382 *area += strlen(*area) + 1; Which seems a little undercooked (TERMCAP_BUFSIZE is 1023), and GDBing to 380 (gdb) p result $4 = 0x5555555e3f12 "\033[%i%p1%d;%p2%dH" for "cm", then a few more, then the last call is for "la", and that crashes. For "la" the result seems to be NULL, so afterward tp is "". Rebuilding screen with asan, I see -- >8 -- $ strace -vs9999 -foss ./screen ^\Quit $ eval "printf %b $(grep 'write(2' ss | cut -c18- | sed 's/, [0-9]*)[ ]*=[ ]*[0-9]*$//' | tr '\n' ' ')" ================================================================= ==3391667==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x519000000e86 at pc 0x559f9edd719a bp 0x7ffd78561dd0 sp 0x7ffd78561588 WRITE of size 7 at 0x519000000e86 thread T0 #0 0x559f9edd7199 in strcpy (/home/nabijaczleweli/uwu/iselect/debian/screen-4.9.1/build/screen+0xde199) (BuildId: c61c99670bf01c54ae47da9eae7a493e6e27987e) #1 0x7f7bd4c17600 /usr/include/x86_64-linux-gnu/bits/string_fortified.h:79:10 #2 0x7f7bd4c17600 in tgetstr_sp obj-wide/ncurses/../../ncurses/tinfo/lib_termcap.c:380:7 #3 0x559f9ee95a77 in e_tgetstr build/../termcap.c:1505:10 #4 0x559f9ee95a77 in InitTermcap build/../termcap.c:157:19 #5 0x559f9ee32ab3 in main build/../screen.c:1390:9 #6 0x7f7bd48e2249 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #7 0x7f7bd48e2304 in __libc_start_main csu/../csu/libc-start.c:360:3 #8 0x559f9ed50960 in _start (/home/nabijaczleweli/uwu/iselect/debian/screen-4.9.1/build/screen+0x57960) (BuildId: c61c99670bf01c54ae47da9eae7a493e6e27987e) 0x519000000e86 is located 0 bytes after 1030-byte region [0x519000000a80,0x519000000e86) allocated by thread T0 here: #0 0x559f9edef75f in malloc (/home/nabijaczleweli/uwu/iselect/debian/screen-4.9.1/build/screen+0xf675f) (BuildId: c61c99670bf01c54ae47da9eae7a493e6e27987e) #1 0x559f9ee957ea in InitTermcap build/../termcap.c:136:27 #2 0x559f9ee32ab3 in main build/../screen.c:1390:9 #3 0x7f7bd48e2249 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/nabijaczleweli/uwu/iselect/debian/screen-4.9.1/build/screen+0xde199) (BuildId: c61c99670bf01c54ae47da9eae7a493e6e27987e) in strcpy Shadow bytes around the buggy address: 0x519000000c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x519000000c80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x519000000d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x519000000d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x519000000e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x519000000e80:[06]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x519000000f00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x519000000f80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x519000001000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x519000001080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x519000001100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==3391667==ABORTING -- >8 -- so they definitely agree here. This looks like a classic buffer overflow: since 382 *area += strlen(*area) + 1; and with ltrace -l '*' -foll screen I can see the Area 3413285 screen->malloc(1030) = 0x561401f95100 and the bumps 3413285 <... tgetstr_sp resumed> ) = 0x561401f95100 3413285 <... tgetstr resumed> , "") = "\033[%i%p1%d;%p2%dH" (this has length 16, so we'd expect the next one to be +17, and whaddaya know) 3413285 <... tgetstr_sp resumed> ) = 0x561401f95111 3413285 <... tgetstr resumed> , "") = "\033[H" and the last non-NULL result is 3413285 <... tgetstr_sp resumed> ) = 0x561401f95556 3413285 <... tgetstr resumed> , "") = "\033OD" which is hex(561401f95556) - hex(561401f95100) = 1110 (+ sizeof("\e0D")), which obviously blows the 1030. turning line 1505 into return tgetstr(cap, NULL); (since per tgetstr(3) under ncurses the buffer is auxiliary) kinda works (after disabling asan, else use-after-free, as expected). Turning line 136 into ...TERMCAP_BUFSIZE * 10... fully works, even under asan. So: 1. where-ever TERMCAP_BUFSIZE=1023 came from, and what-ever it's good for, using it for this allocation is obviously wrong: ncurses does strlcpy(..., 1024) to it, so it must be 1024 for /every/ call to tgetstr() at /least/ 2. this is presumably triggered by st-256color because it has more overall capability string volume than other teletypes? I'm not an expert on terminfo, but this is it: https://git.suckless.org/st/file/st.info.html 3. the easiest fix is probably to just allocate 10k, and to hell with it? 4. a more convoluted but a more correct fix is to tgetstr() to a stack 1k buffer, then just strdup the result, and free it later I have implemented 4., and a patch (accd'g to dpkg-source --commit vs 4.9.1-1) is included below. It passes asan and valgrind. It doesn't pass msan, but this is unrelated to the patch since it also happens with the original implementation regardless of $TERM. Someone who understands screen (not me) should probably try running it with msan and fix the use-after-free :) Best,
--- screen-4.9.1.orig/display.c +++ screen-4.9.1/display.c @@ -334,6 +334,7 @@ struct mode *Mode; } +extern struct term term[]; /* terminal capabilities */ void FreeDisplay() { @@ -357,9 +358,12 @@ FreeDisplay() fcntl(D_userfd, F_SETFL, 0); } freetty(); - if (D_tentry) - free(D_tentry); - D_tentry = 0; + for (size_t i = 0; i < T_N; ++i) + if (term[i].type == T_STR && D_tcs[i].str) + { + free(D_tcs[i].str); + D_tcs[i].str = 0; + } if (D_processinputdata) free(D_processinputdata); D_processinputdata = 0; --- screen-4.9.1.orig/display.h +++ screen-4.9.1/display.h @@ -81,7 +81,6 @@ struct display int d_nonblock; /* -1 don't block if obufmax reached */ /* >0: block after nonblock secs */ char d_termname[MAXTERMLEN + 1]; /* $TERM */ - char *d_tentry; /* buffer for tgetstr */ char d_tcinited; /* termcap inited flag */ int d_width, d_height; /* width/height of the screen */ int d_defwidth, d_defheight; /* default width/height of windows */ @@ -214,7 +213,6 @@ extern struct display TheDisplay; #define D_other DISPLAY(d_other) #define D_nonblock DISPLAY(d_nonblock) #define D_termname DISPLAY(d_termname) -#define D_tentry DISPLAY(d_tentry) #define D_tcinited DISPLAY(d_tcinited) #define D_width DISPLAY(d_width) #define D_height DISPLAY(d_height) --- screen-4.9.1.orig/termcap.c +++ screen-4.9.1/termcap.c @@ -110,7 +110,7 @@ int he; { register char *s; int i; - char tbuf[TERMCAP_BUFSIZE], *tp; + char tbuf[TERMCAP_BUFSIZE < 1024 ? 1024 : TERMCAP_BUFSIZE]; int t, xue, xse, xme; ASSERT(display); @@ -133,16 +133,9 @@ int he; debug1("Extra outcap: %s\n", extra_outcap); #endif - if ((D_tentry = (char *)malloc(TERMCAP_BUFSIZE + (extra_incap ? strlen(extra_incap) + 1 : 0))) == 0) - { - Msg(0, "%s", strnomem); - return -1; - } - /* * loop through all needed capabilities, record their values in the display */ - tp = D_tentry; for (i = 0; i < T_N; i++) { switch(term[i].type) @@ -154,10 +147,15 @@ int he; D_tcs[i].num = e_tgetnum(term[i].tcname); break; case T_STR: - D_tcs[i].str = e_tgetstr(term[i].tcname, &tp); + D_tcs[i].str = e_tgetstr(term[i].tcname, &(char *){tbuf}); /* no empty strings, please */ if (D_tcs[i].str && *D_tcs[i].str == 0) D_tcs[i].str = 0; + if (D_tcs[i].str && !(D_tcs[i].str = strdup(D_tcs[i].str))) + { + Msg(0, "%s", strnomem); + return -1; + } break; default: Panic(0, "Illegal tc type in entry #%d", i);
signature.asc
Description: PGP signature