mirror of
git://slackware.nl/current.git
synced 2024-12-31 10:28:29 +01:00
3874039d9c
patches/packages/coreutils-9.5-x86_64-1_slack15.0.txz: Upgraded. chmod -R now avoids a race where an attacker may replace a traversed file with a symlink, causing chmod to operate on an unintended file. [This bug was present in "the beginning".] split --line-bytes with a mixture of very long and short lines no longer overwrites the heap. For more information, see: https://www.cve.org/CVERecord?id=CVE-2024-0684 (* Security fix *)
207 lines
6.2 KiB
Diff
207 lines
6.2 KiB
Diff
From aa13246a1bf1be9e4f6eb331f4d4d2dbc875e22f Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= <nabijaczleweli@nabijaczleweli.xyz>
|
|
Date: Wed, 15 Mar 2023 16:16:48 +0100
|
|
Subject: [PATCH] wall: use fputs_careful()
|
|
|
|
LINE_MAX only applies to teletypes in canonical mode: when stdin is a
|
|
file, it could still very much tear; start off at 512 for the sprintf(),
|
|
then use getline() like in write.
|
|
|
|
The line wrapping has one suboptimal edge-case:
|
|
$ wall < all
|
|
|
|
Broadcast message from nabijaczleweli@tarta (pts/4) (Tue Mar 14 22:31:25
|
|
2023):
|
|
|
|
^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_
|
|
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ
|
|
KLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~^?\200\201\202\203\204\205\206
|
|
\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232
|
|
\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256
|
|
\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302
|
|
\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326
|
|
\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352
|
|
\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376
|
|
\377
|
|
but that's a pathological input, and the result is still infinitely
|
|
better than it was before, so fixing that is more trouble than it's
|
|
worth.
|
|
|
|
Bug-Debian: https://bugs.debian.org/826596
|
|
---
|
|
include/carefulputc.h | 42 +++++++++++++++++++++++++++++++++---------
|
|
login-utils/last.c | 2 +-
|
|
term-utils/wall.c | 38 ++++++--------------------------------
|
|
term-utils/write.c | 2 +-
|
|
4 files changed, 41 insertions(+), 43 deletions(-)
|
|
|
|
--- a/include/carefulputc.h
|
|
+++ b/include/carefulputc.h
|
|
@@ -6,6 +6,7 @@
|
|
#include <ctype.h>
|
|
#ifdef HAVE_WIDECHAR
|
|
#include <wctype.h>
|
|
+#include <wchar.h>
|
|
#endif
|
|
#include <stdbool.h>
|
|
|
|
@@ -15,18 +16,35 @@
|
|
* A puts() for use in write and wall (that sometimes are sgid tty).
|
|
* It avoids control and invalid characters.
|
|
* The locale of the recipient is nominally unknown,
|
|
- * but it's a solid bet that the encoding is compatible with the author's.
|
|
+ * but it's a solid bet that it's compatible with the author's.
|
|
+ * Use soft_width=0 to disable wrapping.
|
|
*/
|
|
-static inline int fputs_careful(const char * s, FILE *fp, const char ctrl, bool cr_lf)
|
|
+static inline int fputs_careful(const char * s, FILE *fp, const char ctrl, bool cr_lf, int soft_width)
|
|
{
|
|
- int ret = 0;
|
|
+ int ret = 0, col = 0;
|
|
|
|
for (size_t slen = strlen(s); *s; ++s, --slen) {
|
|
- if (*s == '\n')
|
|
+ if (*s == '\t')
|
|
+ col += (7 - (col % 8)) - 1;
|
|
+ else if (*s == '\r')
|
|
+ col = -1;
|
|
+ else if (*s == '\a')
|
|
+ --col;
|
|
+
|
|
+ if ((soft_width && col >= soft_width) || *s == '\n') {
|
|
+ if (soft_width) {
|
|
+ fprintf(fp, "%*s", soft_width - col, "");
|
|
+ col = 0;
|
|
+ }
|
|
ret = fputs(cr_lf ? "\r\n" : "\n", fp);
|
|
- else if (isprint(*s) || *s == '\a' || *s == '\t' || *s == '\r')
|
|
+ if (*s == '\n' || ret < 0)
|
|
+ goto wrote;
|
|
+ }
|
|
+
|
|
+ if (isprint(*s) || *s == '\a' || *s == '\t' || *s == '\r') {
|
|
ret = putc(*s, fp);
|
|
- else if (!c_isascii(*s)) {
|
|
+ ++col;
|
|
+ } else if (!c_isascii(*s)) {
|
|
#ifdef HAVE_WIDECHAR
|
|
wchar_t w;
|
|
size_t clen = mbtowc(&w, s, slen);
|
|
@@ -35,21 +53,27 @@ static inline int fputs_careful(const ch
|
|
case (size_t)-1: // EILSEQ
|
|
mbtowc(NULL, NULL, 0);
|
|
nonprint:
|
|
- ret = fprintf(fp, "\\%3hho", *s);
|
|
+ col += ret = fprintf(fp, "\\%3hho", *s);
|
|
break;
|
|
default:
|
|
if(!iswprint(w))
|
|
goto nonprint;
|
|
ret = fwrite(s, 1, clen, fp);
|
|
+ if (soft_width)
|
|
+ col += wcwidth(w);
|
|
s += clen - 1;
|
|
slen -= clen - 1;
|
|
break;
|
|
}
|
|
#else
|
|
- ret = fprintf(fp, "\\%3hho", *s);
|
|
+ col += ret = fprintf(fp, "\\%3hho", *s);
|
|
#endif
|
|
- } else
|
|
+ } else {
|
|
ret = fputs((char[]){ ctrl, *s ^ 0x40, '\0' }, fp);
|
|
+ col += 2;
|
|
+ }
|
|
+
|
|
+ wrote:
|
|
if (ret < 0)
|
|
return EOF;
|
|
}
|
|
--- a/login-utils/last.c
|
|
+++ b/login-utils/last.c
|
|
@@ -558,7 +558,7 @@ static int list(const struct last_contro
|
|
/*
|
|
* Print out "final" string safely.
|
|
*/
|
|
- fputs_careful(final, stdout, '*', false);
|
|
+ fputs_careful(final, stdout, '*', false, 0);
|
|
|
|
if (len < 0 || (size_t)len >= sizeof(final))
|
|
putchar('\n');
|
|
--- a/term-utils/wall.c
|
|
+++ b/term-utils/wall.c
|
|
@@ -274,29 +274,13 @@ int main(int argc, char **argv)
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
-static void buf_putc_careful(FILE *fs, int c)
|
|
-{
|
|
- if (isprint(c) || c == '\a' || c == '\t' || c == '\r' || c == '\n')
|
|
- fputc(c, fs);
|
|
- else if (!c_isascii(c))
|
|
- fprintf(fs, "\\%3o", (unsigned char)c);
|
|
- else
|
|
- fputs((char[]){ '^', c ^ 0x40, '\0' }, fs);
|
|
-}
|
|
-
|
|
static char *makemsg(char *fname, char **mvec, int mvecsz,
|
|
size_t *mbufsize, int print_banner)
|
|
{
|
|
- register int ch, cnt;
|
|
- char *p, *lbuf, *retbuf;
|
|
+ char *lbuf, *retbuf;
|
|
FILE * fs = open_memstream(&retbuf, mbufsize);
|
|
- long line_max;
|
|
-
|
|
- line_max = sysconf(_SC_LINE_MAX);
|
|
- if (line_max <= 0)
|
|
- line_max = 512;
|
|
-
|
|
- lbuf = xmalloc(line_max);
|
|
+ size_t lbuflen = 512;
|
|
+ lbuf = xmalloc(lbuflen);
|
|
|
|
if (print_banner == TRUE) {
|
|
char *hostname = xgethostname();
|
|
@@ -329,7 +313,7 @@ static char *makemsg(char *fname, char *
|
|
will not overflow as long as %d takes at most 100 chars */
|
|
fprintf(fs, "\r%*s\r\n", TERM_WIDTH, " ");
|
|
|
|
- snprintf(lbuf, line_max,
|
|
+ snprintf(lbuf, lbuflen,
|
|
_("Broadcast message from %s@%s (%s) (%s):"),
|
|
whom, hostname, where, date);
|
|
fprintf(fs, "%-*.*s\007\007\r\n", TERM_WIDTH, TERM_WIDTH, lbuf);
|
|
@@ -373,18 +357,8 @@ static char *makemsg(char *fname, char *
|
|
/*
|
|
* Read message from stdin.
|
|
*/
|
|
- while (fgets(lbuf, line_max, stdin)) {
|
|
- for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) {
|
|
- if (cnt == TERM_WIDTH || ch == '\n') {
|
|
- fprintf(fs, "%*s\r\n", TERM_WIDTH - cnt, "");
|
|
- cnt = 0;
|
|
- }
|
|
- if (ch == '\t')
|
|
- cnt += (7 - (cnt % 8));
|
|
- if (ch != '\n')
|
|
- buf_putc_careful(fs, ch);
|
|
- }
|
|
- }
|
|
+ while (getline(&lbuf, &lbuflen, stdin) >= 0)
|
|
+ fputs_careful(lbuf, fs, '^', true, TERM_WIDTH);
|
|
}
|
|
fprintf(fs, "%*s\r\n", TERM_WIDTH, " ");
|
|
|
|
--- a/term-utils/write.c
|
|
+++ b/term-utils/write.c
|
|
@@ -276,7 +276,7 @@ static void do_write(const struct write_
|
|
if (signal_received)
|
|
break;
|
|
|
|
- if (fputs_careful(line, stdout, '^', true) == EOF)
|
|
+ if (fputs_careful(line, stdout, '^', true, 0) == EOF)
|
|
err(EXIT_FAILURE, _("carefulputc failed"));
|
|
}
|
|
free(line);
|