From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from primenet.com.au (ns1.primenet.com.au [203.24.36.2]) by inbox.vuxu.org (OpenSMTPD) with ESMTP id aa52de0a for ; Fri, 13 Dec 2019 21:09:14 +0000 (UTC) Received: (qmail 29160 invoked by alias); 13 Dec 2019 21:09:08 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: List-Unsubscribe: X-Seq: 45021 Received: (qmail 25607 invoked by uid 1010); 13 Dec 2019 21:09:08 -0000 X-Qmail-Scanner-Diagnostics: from know-smtprelay-omc-5.server.virginmedia.net by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.102.1/25656. spamassassin: 3.4.2. Clear:RC:0(80.0.253.69):SA:0(-2.0/5.0):. Processed in 2.424838 secs); 13 Dec 2019 21:09:08 -0000 X-Envelope-From: p.w.stephenson@ntlworld.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at _smtprelay.virginmedia.com designates 80.0.253.69 as permitted sender) X-Originating-IP: [86.16.88.158] X-Authenticated-User: p.w.stephenson@ntlworld.com X-Spam: 0 X-Authority: v=2.3 cv=Y73WTCWN c=1 sm=1 tr=0 a=MiHCjVqLJ44lE3bxSlffFQ==:117 a=MiHCjVqLJ44lE3bxSlffFQ==:17 a=jpOVt7BSZ2e4Z31A5e1TngXxSK0=:19 a=IkcTkHD0fZMA:10 a=Mrz3sjv-sVQA:10 a=FXF7M35_es6SOlWQGXEA:9 a=QEXdDO2ut3YA:10 Message-ID: <5bd41b45eaf3d745547d1091f4fe22645fd2e8e5.camel@ntlworld.com> Subject: Re: =?ISO-8859-1?Q?TR=A0=3A?= =?ISO-8859-1?Q?_Re=A0=3A?= [BUG] Crash due to malloc call in signal handler From: Peter Stephenson To: zsh-workers@zsh.org Date: Fri, 13 Dec 2019 21:08:27 +0000 In-Reply-To: <1576258224.5214.31.camel@samsung.com> References: <569822988.994307929.1576256973462.JavaMail.root@zimbra62-e11.priv.proxad.net> <1576258224.5214.31.camel@samsung.com> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.28.5-0ubuntu0.18.04.1 Mime-Version: 1.0 Content-Transfer-Encoding: 7bit X-CMAE-Envelope: MS4wfMzH8n8xfrBhx1g3zKHZzX8wNx+NpaAIvKpRcrhUfSVNVZtOKdWsJlJpETuJGTVEJlduE9vgNo30TXspERJ3xtnT7TpsrGc9S3IQAJNEamlDO3QEKCWo b08dxoQE2BT0A61r+pC3f2BcCSY7/ygFh2QLEJn4kP04BlV7MztRLMA+ On Fri, 2019-12-13 at 17:30 +0000, Peter Stephenson wrote: > I think the intention here is to make sure we're not blocking for a long > time in this function, but if fgetc() is doing memory allocation we're > going to have to put that in the signal blocking. However, if the input > itself blocks in fgetc() that's going to be a problem. The fix might be > not to fdopen() the input file, but just read into a buffer with > read(). This would look like the following, which is passing tests... Additional eyes are welcome; I'm not doing a lot of Unix system programming at the moment... pws diff --git a/Src/exec.c b/Src/exec.c index 9dc91a71e..7f23dd824 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -4653,12 +4653,10 @@ mod_export LinkList readoutput(int in, int qt, int *readerror) { LinkList ret; - char *buf, *ptr; - int bsiz, c, cnt = 0; - FILE *fin; + char *buf, *bufptr, *ptr, inbuf[64]; + int bsiz, c, cnt = 0, readret; int q = queue_signal_level(); - fin = fdopen(in, "r"); ret = newlinklist(); ptr = buf = (char *) hcalloc(bsiz = 64); /* @@ -4670,33 +4668,37 @@ readoutput(int in, int qt, int *readerror) */ dont_queue_signals(); child_unblock(); - while ((c = fgetc(fin)) != EOF || errno == EINTR) { - if (c == EOF) { - errno = 0; - clearerr(fin); - continue; - } - if (imeta(c)) { - *ptr++ = Meta; - c ^= 32; - cnt++; + for (;;) { + readret = read(in, inbuf, 64); + if (readret <= 0) { + if (readret < 0 && errno == EINTR) + continue; + else + break; } - if (++cnt >= bsiz) { - char *pp; - queue_signals(); - pp = (char *) hcalloc(bsiz *= 2); - dont_queue_signals(); + for (bufptr = inbuf; bufptr < inbuf + readret; bufptr++) { + c = *bufptr; + if (imeta(c)) { + *ptr++ = Meta; + c ^= 32; + cnt++; + } + if (++cnt >= bsiz) { + char *pp; + queue_signals(); + pp = (char *) hcalloc(bsiz *= 2); + dont_queue_signals(); - memcpy(pp, buf, cnt - 1); - ptr = (buf = pp) + cnt - 1; + memcpy(pp, buf, cnt - 1); + ptr = (buf = pp) + cnt - 1; + } + *ptr++ = c; } - *ptr++ = c; } child_block(); restore_queue_signals(q); if (readerror) - *readerror = ferror(fin) ? errno : 0; - fclose(fin); + *readerror = readret < 0 ? errno : 0; while (cnt && ptr[-1] == '\n') ptr--, cnt--; *ptr = '\0';