summaryrefslogtreecommitdiff
path: root/usr.bin/less
diff options
context:
space:
mode:
authorTheo Buehler <tb@cvs.openbsd.org>2024-04-14 08:34:01 +0000
committerTheo Buehler <tb@cvs.openbsd.org>2024-04-14 08:34:01 +0000
commit23798ca9c70b0cbe85b6221fe9944f04c970434c (patch)
tree21385d16301a4d197462733db140a96172337957 /usr.bin/less
parentfa33e8cf95b060553529ddddf7093ee42294f9cc (diff)
less: escape newlines in file names
Newlines in a filename can lead to arbitrary code execution https://marc.info/?l=oss-security&m=171292433330233&w=2 via LESSOPEN. The diff is a straightforward adaptation of https://github.com/gwsw/less/commit/007521ac3c95bc76 The better fix is deleting the misfeatures that are LESSOPEN and LESSCLOSE which will happen in a separate commit. diff looks good to guenther
Diffstat (limited to 'usr.bin/less')
-rw-r--r--usr.bin/less/filename.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/usr.bin/less/filename.c b/usr.bin/less/filename.c
index 8b2dd9a02f4..dfe998fe9e3 100644
--- a/usr.bin/less/filename.c
+++ b/usr.bin/less/filename.c
@@ -107,6 +107,15 @@ metachar(char c)
}
/*
+ * Must use quotes rather than escape characters for this meta character.
+ */
+static int
+must_quote(char c)
+{
+ return (c == '\n');
+}
+
+/*
* Insert a backslash before each metacharacter in a string.
*/
char *
@@ -136,6 +145,9 @@ shell_quote(const char *s)
* doesn't support escape chars. Use quotes.
*/
use_quotes = 1;
+ } else if (must_quote(*p)) {
+ /* Opening quote + character + closing quote. */
+ len += 3;
} else {
/*
* Allow space for the escape char.
@@ -155,14 +167,19 @@ shell_quote(const char *s)
} else {
newstr = r = ecalloc(len, sizeof (char));
while (*s != '\0') {
- if (metachar(*s)) {
- /*
- * Add the escape char.
- */
+ if (!metachar(*s)) {
+ *r++ = *s++;
+ } else if (must_quote(*s)) {
+ /* Surround the character with quotes. */
+ *r++ = openquote;
+ *r++ = *s++;
+ *r++ = closequote;
+ } else {
+ /* Escape the character. */
(void) strlcpy(r, esc, newstr + len - p);
r += esclen;
+ *r++ = *s++;
}
- *r++ = *s++;
}
*r = '\0';
}