Re: [PATCH bpf v2 1/2] bpf: allow UTF-8 literals in bpf_bprintf_prepare()

From: Paul Chaignon

Date: Wed Apr 15 2026 - 06:49:33 EST


On Wed, Apr 15, 2026 at 12:45:02PM +0200, Paul Chaignon wrote:
> On Wed, Apr 15, 2026 at 11:21:25AM +0800, Yihan Ding wrote:
> > bpf_bprintf_prepare() only needs ASCII parsing for conversion
> > specifiers. Plain text can safely carry bytes >= 0x80, so allow
> > UTF-8 literals outside '%' sequences while keeping ASCII control
> > bytes rejected and format specifiers ASCII-only.
> >
> > This keeps existing parsing rules for format directives unchanged,
> > while allowing helpers such as bpf_trace_printk() to emit UTF-8
> > literal text.
> >
> > Fixes: 48cac3f4a96d ("bpf: Implement formatted output helpers with bstr_printf")
> > Suggested-by: Paul Chaignon <paul.chaignon@xxxxxxxxx>
>
> I don't think this tag is appropriate here. If you want to give credit
> for changes made after reviews, you can do so in the Changelogs of the
> cover letter :)
>
> > Signed-off-by: Yihan Ding <dingyihan@xxxxxxxxxxxxx>
> > ---
> > kernel/bpf/helpers.c | 16 +++++++++++++++-
> > 1 file changed, 15 insertions(+), 1 deletion(-)
> >
> > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> > index 6eb6c82ed2ee..6319b39c92f9 100644
> > --- a/kernel/bpf/helpers.c
> > +++ b/kernel/bpf/helpers.c
> > @@ -845,7 +845,13 @@ int bpf_bprintf_prepare(const char *fmt, u32 fmt_size, const u64 *raw_args,
> > data->buf = buffers->buf;
> >
> > for (i = 0; i < fmt_size; i++) {
> > - if ((!isprint(fmt[i]) && !isspace(fmt[i])) || !isascii(fmt[i])) {
> > + unsigned char c = fmt[i];
> > +
> > + /*
> > + * Permit bytes >= 0x80 in plain text so UTF-8 literals can pass
> > + * through unchanged, while still rejecting ASCII control bytes.
> > + */
> > + if (isascii(c) && !isprint(c) && !isspace(c)) {
> > err = -EINVAL;
> > goto out;
> > }
> > @@ -867,6 +873,14 @@ int bpf_bprintf_prepare(const char *fmt, u32 fmt_size, const u64 *raw_args,
> > * always access fmt[i + 1], in the worst case it will be a 0
> > */
> > i++;
> > + /*
> > + * The format parser below only understands ASCII conversion
> > + * specifiers and modifiers, so reject non-ASCII after '%'.
> > + */
> > + if (!isascii((unsigned char)fmt[i])) {
> > + err = -EINVAL;
> > + goto out;
> > + }
>
> Acked-by: Paul Chaignon <paul.chaignon@xxxxxxxxx>

Actually, this patch will require changes to fixup the existing
test_snprintf_negative() selftest that is currently failing. That fixup
needs to be in this commit to not break selftests during bisections.

>
> >
> > /* skip optional "[0 +-][num]" width formatting field */
> > while (fmt[i] == '0' || fmt[i] == '+' || fmt[i] == '-' ||
> > --
> > 2.20.1