public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: David Laight <david.laight.linux@gmail.com>
To: "Thomas Weißschuh" <linux@weissschuh.net>
Cc: Willy Tarreau <w@1wt.eu>,
	linux-kernel@vger.kernel.org, Cheng Li <lechain@gmail.com>
Subject: Re: [PATCH v3 next 07/17] tools/nolibc/printf: Move snprintf length check to callback
Date: Wed, 25 Feb 2026 23:12:21 +0000	[thread overview]
Message-ID: <20260225231221.70b0531f@pumpkin> (raw)
In-Reply-To: <bcc3b413-e209-4d1c-ab3f-d33b467fe4c8@t-8ch.de>

On Wed, 25 Feb 2026 23:37:42 +0100
Thomas Weißschuh <linux@weissschuh.net> wrote:

> On 2026-02-23 10:17:25+0000, david.laight.linux@gmail.com wrote:
> 
> (...)
> 
> > @@ -425,18 +430,25 @@ int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char
> >  
> >  		/* literal char, just queue it */
> >  	}
> > +
> > +	/* Request a final '\0' be added to the snprintf() output.
> > +	 * This may be the only call of the cb() function.
> > +	 */
> > +	if (cb(state, NULL, 0) != 0)
> > +		return -1;
> > +
> >  	return written;
> >  }  
> 
> (...)
> 
> > +static int __nolibc_sprintf_cb(void *v_state, const char *buf, size_t size)
> >  {
> > -	char **state = (char **)_state;
> > +	struct __nolibc_sprintf_cb_state *state = v_state;
> > +	size_t space = state->space;
> > +	char *tgt;
> > +
> > +	/* Truncate the request to fit in the output buffer space.
> > +	 * The last byte is reserved for the terminating '\0'.
> > +	 * state->space can only be zero for snprintf(NULL, 0, fmt, args)
> > +	 * so this normally lets through calls with 'size == 0'.
> > +	 */
> > +	if (size >= space) {
> > +		if (space <= 1)
> > +			return 0;
> > +		size = space - 1;
> > +	}
> > +	tgt = state->buf;
> > +
> > +	/* __nolibc_printf() ends with cb(state, NULL, 0) to request the output
> > +	 * buffer be '\0' terminated.
> > +	 * That will be the only cb() call for, eg, snprintf(buf, sz, "").
> > +	 * Zero lengths can occur at other times (eg "%s" for an empty string).
> > +	 * Unconditionally write the '\0' byte to reduce code size, it is
> > +	 * normally overwritten by the data being output.
> > +	 * There is no point adding a '\0' after copied data - there is always
> > +	 * another call.
> > +	 */
> > +	*tgt = '\0';
> > +	state->space = space - size;
> > +	state->buf = tgt + size;
> > +	memcpy(tgt, buf, size);  
> 
> This trips UBSAN for me when 'buf == NULL'.
> 
> if (cb(state, NULL, 0) != 0)
> 	return -1;
> 
> It can be fixed by adding a NULL check around memcpy(),
> but I'd rather not do this as a random fixup.

Blame Willy, he made me remove the 'if (size)' check to reduce
the code size.
The '*tgt = 0' line is (only) needed when size is zero, the other lines
are clearly pointless.
So the 'random fixup' is adding 'if (size)' rather than a NULL
pointer check
printf("%s", "") will give a zero size with non-NULL buf.

IIRC the C standard make memcpy(tgt, NULL, 0) UB because some old system
no one has used for 40+ years would trap when NULL was loaded into an
'address register' and they wanted it to be compliant.

	David

> 
> >  
> > -	memcpy(*state, buf, size);
> > -	*state += size;
> >  	return 0;
> >  }  
> 
> (...)


  reply	other threads:[~2026-02-25 23:12 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-23 10:17 [PATCH v3 next 00/17] Enhance printf() david.laight.linux
2026-02-23 10:17 ` [PATCH v3 next 01/17] tools/nolibc: Add _NOLIBC_OPTIMIZER_HIDE_VAR() to compiler.h david.laight.linux
2026-02-25 21:25   ` Thomas Weißschuh
2026-02-25 22:17     ` David Laight
2026-02-25 22:24       ` Thomas Weißschuh
2026-02-23 10:17 ` [PATCH v3 next 02/17] tools/nolibc: Optimise and common up the number to ascii functions david.laight.linux
2026-02-25 21:40   ` Thomas Weißschuh
2026-02-25 22:09     ` David Laight
2026-02-23 10:17 ` [PATCH v3 next 03/17] selftests/nolibc: Fix build with host headers and libc david.laight.linux
2026-02-25 21:24   ` Thomas Weißschuh
2026-02-23 10:17 ` [PATCH v3 next 04/17] selftests/nolibc: Improve reporting of vfprintf() errors david.laight.linux
2026-02-25 21:56   ` Thomas Weißschuh
2026-02-26 10:12     ` David Laight
2026-02-26 21:39       ` Thomas Weißschuh
2026-02-23 10:17 ` [PATCH v3 next 05/17] tools/nolibc: Implement strerror() in terms of strerror_r() david.laight.linux
2026-02-25 22:09   ` Thomas Weißschuh
2026-02-25 22:58     ` David Laight
2026-02-23 10:17 ` [PATCH v3 next 06/17] tools/nolibc/printf: Change variables 'c' to 'ch' and 'tmpbuf[]' to 'outbuf[]' david.laight.linux
2026-02-25 22:23   ` Thomas Weißschuh
2026-02-23 10:17 ` [PATCH v3 next 07/17] tools/nolibc/printf: Move snprintf length check to callback david.laight.linux
2026-02-25 22:37   ` Thomas Weißschuh
2026-02-25 23:12     ` David Laight [this message]
2026-02-26 21:29       ` Thomas Weißschuh
2026-02-26 22:11         ` David Laight
2026-02-23 10:17 ` [PATCH v3 next 08/17] tools/nolibc/printf: Output pad characters in 16 byte chunks david.laight.linux
2026-02-23 10:17 ` [PATCH v3 next 09/17] tools/nolibc/printf: Simplify __nolibc_printf() david.laight.linux
2026-02-23 10:17 ` [PATCH v3 next 10/17] tools/nolibc/printf: Use goto and reduce indentation david.laight.linux
2026-02-23 10:17 ` [PATCH v3 next 11/17] tools/nolibc/printf: Use bit-masks to hold requested flag, length and conversion chars david.laight.linux
2026-02-23 10:17 ` [PATCH v3 next 12/17] tools/nolibc/printf: Handle "%s" with the numeric formats david.laight.linux
2026-02-23 10:17 ` [PATCH v3 next 13/17] tools/nolibc/printf: Add support for conversion flags david.laight.linux
2026-02-23 10:17 ` [PATCH v3 next 14/17] tools/nolibc/printf: Add support for left aligning fields david.laight.linux
2026-02-23 10:17 ` [PATCH v3 next 15/17] tools/nolibc/printf: Add support for zero padding and field precision david.laight.linux
2026-02-23 10:17 ` [PATCH v3 next 16/17] tools/nolibc/printf: Add support for octal output david.laight.linux
2026-02-23 10:17 ` [PATCH v3 next 17/17] selftests/nolibc: Use printf variable field widths and precisions david.laight.linux

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=20260225231221.70b0531f@pumpkin \
    --to=david.laight.linux@gmail.com \
    --cc=lechain@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@weissschuh.net \
    --cc=w@1wt.eu \
    /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