summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2022-12-18 19:01:10 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2022-12-19 12:33:57 -0800
commit03488eeea9cef99e2fa6c29d43b4befcc3e6ce40 (patch)
tree38f1a4047055a41fd4a98ffff45b13966b67b962
parent2aa368b97046554c5841ef69d05458854a753252 (diff)
downloadsed-03488eeea9cef99e2fa6c29d43b4befcc3e6ce40.tar.gz
sed: do octal escapes ourselves
* sed/execute.c (do_list): Simplify by doing octal escapes by hand (!) instead of having sprintf do it. This makes it easier for compilers and humans see that buffer overflow is impossible. And it’s quite a bit faster if the input consists mostly of odd control bytes.
-rw-r--r--sed/execute.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/sed/execute.c b/sed/execute.c
index 485bca7..529ae47 100644
--- a/sed/execute.c
+++ b/sed/execute.c
@@ -905,14 +905,12 @@ do_list (int line_len)
unsigned char *p = (unsigned char *)line.active;
countT len = line.length;
countT width = 0;
- char obuf[180]; /* just in case we encounter a 512-bit char (;-) */
- char *o;
- size_t olen;
FILE *fp = output_file.fp;
output_missing_newline (&output_file);
for (; len--; ++p) {
- o = obuf;
+ char obuf[sizeof "\\377" - 1];
+ char *o = obuf;
/* Some locales define 8-bit characters as printable. This makes the
testsuite fail at 8to7.sed because the `l' command in fact will not
@@ -940,12 +938,13 @@ do_list (int line_len)
case '\t': *o++ = 't'; break;
case '\v': *o++ = 'v'; break;
default:
- sprintf (o, "%03o", *p);
- o += strlen (o);
+ *o++ = '0' + ((*p & 0300) >> 6);
+ *o++ = '0' + ((*p & 0070) >> 3);
+ *o++ = '0' + ((*p & 0007) >> 0);
break;
}
}
- olen = o - obuf;
+ size_t olen = o - obuf;
if (width+olen >= line_len && line_len > 0) {
ck_fwrite ("\\", 1, 1, fp);
ck_fwrite (&buffer_delimiter, 1, 1, fp);