From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
To: linux-kernel@vger.kernel.org, pmladek@suse.com,
Kent Overstreet <kent.overstreet@gmail.com>
Cc: Andy Shevchenko <andy@kernel.org>
Subject: [PATCH v5 02/32] lib/string_helpers: Convert string_escape_mem() to printbuf
Date: Mon, 8 Aug 2022 03:40:58 +0100 [thread overview]
Message-ID: <20220808024128.3219082-3-willy@infradead.org> (raw)
In-Reply-To: <20220808024128.3219082-1-willy@infradead.org>
From: Kent Overstreet <kent.overstreet@gmail.com>
Like the upcoming vsprintf.c conversion, this converts string_escape_mem
to prt_escaped_string(), which uses and outputs to a printbuf, and makes
string_escape_mem() a smaller wrapper to support existing users.
The new printbuf helpers greatly simplify the code.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Cc: Andy Shevchenko <andy@kernel.org>
---
include/linux/string_helpers.h | 4 +
lib/string_helpers.c | 217 ++++++++++++++++++---------------
2 files changed, 126 insertions(+), 95 deletions(-)
diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h
index 4d72258d42fd..67de398944e8 100644
--- a/include/linux/string_helpers.h
+++ b/include/linux/string_helpers.h
@@ -10,6 +10,7 @@
struct device;
struct file;
struct task_struct;
+struct printbuf;
/* Descriptions of the types of units to
* print in */
@@ -62,6 +63,8 @@ static inline int string_unescape_any_inplace(char *buf)
#define ESCAPE_ALL_MASK GENMASK(8, 0)
+void prt_escaped_string(struct printbuf *out, const char *src, size_t isz,
+ unsigned int flags, const char *only);
int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
unsigned int flags, const char *only);
@@ -71,6 +74,7 @@ static inline int string_escape_mem_any_np(const char *src, size_t isz,
return string_escape_mem(src, isz, dst, osz, ESCAPE_ANY_NP, only);
}
+
static inline int string_escape_str(const char *src, char *dst, size_t sz,
unsigned int flags, const char *only)
{
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 5ed3beb066e6..7be20bcc6137 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -15,6 +15,7 @@
#include <linux/fs.h>
#include <linux/limits.h>
#include <linux/mm.h>
+#include <linux/printbuf.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/string_helpers.h>
@@ -301,19 +302,14 @@ int string_unescape(char *src, char *dst, size_t size, unsigned int flags)
}
EXPORT_SYMBOL(string_unescape);
-static bool escape_passthrough(unsigned char c, char **dst, char *end)
+static bool escape_passthrough(struct printbuf *out, unsigned char c)
{
- char *out = *dst;
-
- if (out < end)
- *out = c;
- *dst = out + 1;
+ prt_char(out, c);
return true;
}
-static bool escape_space(unsigned char c, char **dst, char *end)
+static bool escape_space(struct printbuf *out, unsigned char c)
{
- char *out = *dst;
unsigned char to;
switch (c) {
@@ -336,20 +332,13 @@ static bool escape_space(unsigned char c, char **dst, char *end)
return false;
}
- if (out < end)
- *out = '\\';
- ++out;
- if (out < end)
- *out = to;
- ++out;
-
- *dst = out;
+ prt_char(out, '\\');
+ prt_char(out, to);
return true;
}
-static bool escape_special(unsigned char c, char **dst, char *end)
+static bool escape_special(struct printbuf *out, unsigned char c)
{
- char *out = *dst;
unsigned char to;
switch (c) {
@@ -369,83 +358,43 @@ static bool escape_special(unsigned char c, char **dst, char *end)
return false;
}
- if (out < end)
- *out = '\\';
- ++out;
- if (out < end)
- *out = to;
- ++out;
-
- *dst = out;
+ prt_char(out, '\\');
+ prt_char(out, to);
return true;
}
-static bool escape_null(unsigned char c, char **dst, char *end)
+static bool escape_null(struct printbuf *out, unsigned char c)
{
- char *out = *dst;
-
if (c)
return false;
- if (out < end)
- *out = '\\';
- ++out;
- if (out < end)
- *out = '0';
- ++out;
-
- *dst = out;
+ prt_char(out, '\\');
+ prt_char(out, '0');
return true;
}
-static bool escape_octal(unsigned char c, char **dst, char *end)
+static bool escape_octal(struct printbuf *out, unsigned char c)
{
- char *out = *dst;
-
- if (out < end)
- *out = '\\';
- ++out;
- if (out < end)
- *out = ((c >> 6) & 0x07) + '0';
- ++out;
- if (out < end)
- *out = ((c >> 3) & 0x07) + '0';
- ++out;
- if (out < end)
- *out = ((c >> 0) & 0x07) + '0';
- ++out;
-
- *dst = out;
+ prt_char(out, '\\');
+ prt_char(out, ((c >> 6) & 0x07) + '0');
+ prt_char(out, ((c >> 3) & 0x07) + '0');
+ prt_char(out, ((c >> 0) & 0x07) + '0');
return true;
}
-static bool escape_hex(unsigned char c, char **dst, char *end)
+static bool escape_hex(struct printbuf *out, unsigned char c)
{
- char *out = *dst;
-
- if (out < end)
- *out = '\\';
- ++out;
- if (out < end)
- *out = 'x';
- ++out;
- if (out < end)
- *out = hex_asc_hi(c);
- ++out;
- if (out < end)
- *out = hex_asc_lo(c);
- ++out;
-
- *dst = out;
+ prt_char(out, '\\');
+ prt_char(out, 'x');
+ prt_hex_byte(out, c);
return true;
}
/**
- * string_escape_mem - quote characters in the given memory buffer
+ * prt_escaped_string - quote characters in the given memory buffer
+ * @out: printbuf to output to (escaped)
* @src: source buffer (unescaped)
* @isz: source buffer size
- * @dst: destination buffer (escaped)
- * @osz: destination buffer size
* @flags: combination of the flags
* @only: NULL-terminated string containing characters used to limit
* the selected escape class. If characters are included in @only
@@ -510,18 +459,11 @@ static bool escape_hex(unsigned char c, char **dst, char *end)
* or %ESCAPE_HEX, because they cover most of the other character classes.
* %ESCAPE_NAP can utilize %ESCAPE_SPACE or %ESCAPE_SPECIAL in addition to
* the above.
- *
- * Return:
- * The total size of the escaped output that would be generated for
- * the given input and flags. To check whether the output was
- * truncated, compare the return value to osz. There is room left in
- * dst for a '\0' terminator if and only if ret < osz.
*/
-int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
- unsigned int flags, const char *only)
+void prt_escaped_string(struct printbuf *out,
+ const char *src, size_t isz,
+ unsigned int flags, const char *only)
{
- char *p = dst;
- char *end = p + osz;
bool is_dict = only && *only;
bool is_append = flags & ESCAPE_APPEND;
@@ -549,41 +491,126 @@ int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
* %ESCAPE_NA cases.
*/
if (!(is_append || in_dict) && is_dict &&
- escape_passthrough(c, &p, end))
+ escape_passthrough(out, c))
continue;
if (!(is_append && in_dict) && isascii(c) && isprint(c) &&
- flags & ESCAPE_NAP && escape_passthrough(c, &p, end))
+ flags & ESCAPE_NAP && escape_passthrough(out, c))
continue;
if (!(is_append && in_dict) && isprint(c) &&
- flags & ESCAPE_NP && escape_passthrough(c, &p, end))
+ flags & ESCAPE_NP && escape_passthrough(out, c))
continue;
if (!(is_append && in_dict) && isascii(c) &&
- flags & ESCAPE_NA && escape_passthrough(c, &p, end))
+ flags & ESCAPE_NA && escape_passthrough(out, c))
continue;
- if (flags & ESCAPE_SPACE && escape_space(c, &p, end))
+ if (flags & ESCAPE_SPACE && escape_space(out, c))
continue;
- if (flags & ESCAPE_SPECIAL && escape_special(c, &p, end))
+ if (flags & ESCAPE_SPECIAL && escape_special(out, c))
continue;
- if (flags & ESCAPE_NULL && escape_null(c, &p, end))
+ if (flags & ESCAPE_NULL && escape_null(out, c))
continue;
/* ESCAPE_OCTAL and ESCAPE_HEX always go last */
- if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end))
+ if (flags & ESCAPE_OCTAL && escape_octal(out, c))
continue;
- if (flags & ESCAPE_HEX && escape_hex(c, &p, end))
+ if (flags & ESCAPE_HEX && escape_hex(out, c))
continue;
- escape_passthrough(c, &p, end);
+ escape_passthrough(out, c);
}
+}
+EXPORT_SYMBOL(prt_escaped_string);
+
+/**
+ * string_escape_mem - quote characters in the given memory buffer
+ * @src: source buffer (unescaped)
+ * @isz: source buffer size
+ * @dst: destination buffer (escaped)
+ * @osz: destination buffer size
+ * @flags: combination of the flags
+ * @only: NULL-terminated string containing characters used to limit
+ * the selected escape class. If characters are included in @only
+ * that would not normally be escaped by the classes selected
+ * in @flags, they will be copied to @dst unescaped.
+ *
+ * Description:
+ * The process of escaping byte buffer includes several parts. They are applied
+ * in the following sequence.
+ *
+ * 1. The character is not matched to the one from @only string and thus
+ * must go as-is to the output.
+ * 2. The character is matched to the printable and ASCII classes, if asked,
+ * and in case of match it passes through to the output.
+ * 3. The character is matched to the printable or ASCII class, if asked,
+ * and in case of match it passes through to the output.
+ * 4. The character is checked if it falls into the class given by @flags.
+ * %ESCAPE_OCTAL and %ESCAPE_HEX are going last since they cover any
+ * character. Note that they actually can't go together, otherwise
+ * %ESCAPE_HEX will be ignored.
+ *
+ * Caller must provide valid source and destination pointers. Be aware that
+ * destination buffer will not be NULL-terminated, thus caller have to append
+ * it if needs. The supported flags are::
+ *
+ * %ESCAPE_SPACE: (special white space, not space itself)
+ * '\f' - form feed
+ * '\n' - new line
+ * '\r' - carriage return
+ * '\t' - horizontal tab
+ * '\v' - vertical tab
+ * %ESCAPE_SPECIAL:
+ * '\"' - double quote
+ * '\\' - backslash
+ * '\a' - alert (BEL)
+ * '\e' - escape
+ * %ESCAPE_NULL:
+ * '\0' - null
+ * %ESCAPE_OCTAL:
+ * '\NNN' - byte with octal value NNN (3 digits)
+ * %ESCAPE_ANY:
+ * all previous together
+ * %ESCAPE_NP:
+ * escape only non-printable characters, checked by isprint()
+ * %ESCAPE_ANY_NP:
+ * all previous together
+ * %ESCAPE_HEX:
+ * '\xHH' - byte with hexadecimal value HH (2 digits)
+ * %ESCAPE_NA:
+ * escape only non-ascii characters, checked by isascii()
+ * %ESCAPE_NAP:
+ * escape only non-printable or non-ascii characters
+ * %ESCAPE_APPEND:
+ * append characters from @only to be escaped by the given classes
+ *
+ * %ESCAPE_APPEND would help to pass additional characters to the escaped, when
+ * one of %ESCAPE_NP, %ESCAPE_NA, or %ESCAPE_NAP is provided.
+ *
+ * One notable caveat, the %ESCAPE_NAP, %ESCAPE_NP and %ESCAPE_NA have the
+ * higher priority than the rest of the flags (%ESCAPE_NAP is the highest).
+ * It doesn't make much sense to use either of them without %ESCAPE_OCTAL
+ * or %ESCAPE_HEX, because they cover most of the other character classes.
+ * %ESCAPE_NAP can utilize %ESCAPE_SPACE or %ESCAPE_SPECIAL in addition to
+ * the above.
+ *
+ * Return:
+ * The total size of the escaped output that would be generated for
+ * the given input and flags. To check whether the output was
+ * truncated, compare the return value to osz. There is room left in
+ * dst for a '\0' terminator if and only if ret < osz.
+ */
+int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
+ unsigned int flags, const char *only)
+{
+ struct printbuf out = PRINTBUF_EXTERN(dst, osz);
- return p - dst;
+ prt_escaped_string(&out, src, isz, flags, only);
+ return out.pos;
}
EXPORT_SYMBOL(string_escape_mem);
--
2.35.1
next prev parent reply other threads:[~2022-08-08 2:42 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-08 2:40 [PATCH v5 00/32] Printbufs Matthew Wilcox (Oracle)
2022-08-08 2:40 ` [PATCH v5 01/32] lib/printbuf: New data structure for printing strings Matthew Wilcox (Oracle)
2022-08-08 2:40 ` Matthew Wilcox (Oracle) [this message]
2022-08-08 12:03 ` [PATCH v5 02/32] lib/string_helpers: Convert string_escape_mem() to printbuf Andy Shevchenko
2022-08-08 14:58 ` Kent Overstreet
2022-08-08 2:40 ` [PATCH v5 03/32] vsprintf: Convert " Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 04/32] lib/hexdump: " Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 05/32] lib/string_helpers: string_get_size() now returns characters wrote Matthew Wilcox (Oracle)
2022-08-08 13:08 ` Andy Shevchenko
2022-08-08 2:41 ` [PATCH v5 06/32] lib/printbuf: Heap allocation Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 07/32] lib/printbuf: Tabstops, indenting Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 08/32] lib/printbuf: Unit specifiers Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 09/32] vsprintf: Improve number() Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 10/32] vsprintf: prt_u64_minwidth(), prt_u64() Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 11/32] test_printf: Drop requirement that sprintf not write past nul Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 12/32] vsprintf: Start consolidating printf_spec handling Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 13/32] vsprintf: Refactor resource_string() Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 14/32] vsprintf: Refactor fourcc_string() Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 15/32] vsprintf: Refactor ip_addr_string() Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 16/32] vsprintf: Refactor mac_address_string() Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 17/32] vsprintf: time_and_date() no longer takes printf_spec Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 18/32] vsprintf: flags_string() " Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 19/32] vsprintf: Refactor device_node_string, fwnode_string Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 20/32] vsprintf: Refactor hex_string, bitmap_string_list, bitmap_string Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 21/32] Input/joystick/analog: Convert from seq_buf -> printbuf Matthew Wilcox (Oracle)
2022-08-11 1:37 ` Dmitry Torokhov
2022-08-08 2:41 ` [PATCH v5 22/32] mm/memcontrol.c: Convert to printbuf Matthew Wilcox (Oracle)
2022-08-08 9:48 ` Michal Hocko
2022-08-08 12:48 ` Michal Hocko
2022-08-08 2:41 ` [PATCH v5 23/32] clk: tegra: bpmp: " Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 24/32] tools/testing/nvdimm: " Matthew Wilcox (Oracle)
2022-08-08 18:30 ` Dan Williams
2022-08-08 18:33 ` Kent Overstreet
2022-08-08 2:41 ` [PATCH v5 25/32] powerpc: " Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 26/32] x86/resctrl: " Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 27/32] PCI/P2PDMA: " Matthew Wilcox (Oracle)
2022-08-08 17:51 ` Bjorn Helgaas
2022-08-08 18:42 ` Kent Overstreet
2022-08-09 2:07 ` Bjorn Helgaas
2022-08-09 8:00 ` Christoph Hellwig
2022-08-08 2:41 ` [PATCH v5 28/32] tracing: trace_events_synth: " Matthew Wilcox (Oracle)
2022-08-08 2:41 ` [PATCH v5 29/32] d_path: prt_path() Matthew Wilcox (Oracle)
2022-08-08 4:17 ` Al Viro
2022-08-08 4:27 ` Kent Overstreet
2022-08-08 2:41 ` [PATCH v5 30/32] ACPI/APEI: Add missing include Matthew Wilcox (Oracle)
2022-08-08 14:09 ` Rafael J. Wysocki
2022-08-08 2:41 ` [PATCH v5 31/32] tracing: Convert to printbuf Matthew Wilcox (Oracle)
2022-08-08 2:51 ` Steven Rostedt
2022-08-08 3:32 ` Kent Overstreet
2022-08-08 13:37 ` Steven Rostedt
2022-08-08 15:15 ` Kent Overstreet
2022-08-08 15:25 ` Steven Rostedt
2022-08-08 2:41 ` [PATCH v5 32/32] Delete seq_buf Matthew Wilcox (Oracle)
2022-09-23 7:10 ` [PATCH v5 00/32] Printbufs Petr Mladek
2022-09-24 1:39 ` Kent Overstreet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220808024128.3219082-3-willy@infradead.org \
--to=willy@infradead.org \
--cc=andy@kernel.org \
--cc=kent.overstreet@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=pmladek@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox