Messages in this thread | | | Date | Wed, 23 Jun 2021 12:16:08 +0300 | From | Andy Shevchenko <> | Subject | Re: [PATCH v2 3/4] lib/test_printf.c: split write-beyond-buffer check in two |
| |
On Wed, Jun 23, 2021 at 01:50:10PM +0800, Jia He wrote: > From: Rasmus Villemoes <linux@rasmusvillemoes.dk> > > Before each invocation of vsnprintf(), do_test() memsets the entire > allocated buffer to a sentinel value. That buffer includes leading and > trailing padding which is never included in the buffer area handed to > vsnprintf (spaces merely for clarity): > > pad test_buffer pad > **** **************** **** > > Then vsnprintf() is invoked with a bufsize argument <= > BUF_SIZE. Suppose bufsize=10, then we'd have e.g. > > |pad | test_buffer |pad | > **** pizza0 **** ****** **** > A B C D E > > where vsnprintf() was given the area from B to D. > > It is obviously a bug for vsnprintf to touch anything between A and B > or between D and E. The former is checked for as one would expect. But > for the latter, we are actually a little stricter in that we check the > area between C and E. > > Split that check in two, providing a clearer error message in case it > was a genuine buffer overrun and not merely a write within the > provided buffer, but after the end of the generated string. > > So far, no part of the vsnprintf() implementation has had any use for > using the whole buffer as scratch space, but it's not unreasonable to > allow that, as long as the result is properly nul-terminated and the > return value is the right one. However, it is somewhat unusual, and > most %<something> won't need this, so keep the [C,D] check, but make > it easy for a later patch to make that part opt-out for certain tests.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> > Tested-by: Jia He <justin.he@arm.com> > Signed-off-by: Jia He <justin.he@arm.com> > Reviewed-by: Petr Mladek <pmladek@suse.com> > --- > lib/test_printf.c | 7 ++++++- > 1 file changed, 6 insertions(+), 1 deletion(-) > > diff --git a/lib/test_printf.c b/lib/test_printf.c > index ec0d5976bb69..d1d2f898ebae 100644 > --- a/lib/test_printf.c > +++ b/lib/test_printf.c > @@ -78,12 +78,17 @@ do_test(int bufsize, const char *expect, int elen, > return 1; > } > > - if (memchr_inv(test_buffer + written + 1, FILL_CHAR, BUF_SIZE + PAD_SIZE - (written + 1))) { > + if (memchr_inv(test_buffer + written + 1, FILL_CHAR, bufsize - (written + 1))) { > pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote beyond the nul-terminator\n", > bufsize, fmt); > return 1; > } > > + if (memchr_inv(test_buffer + bufsize, FILL_CHAR, BUF_SIZE + PAD_SIZE - bufsize)) { > + pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote beyond buffer\n", bufsize, fmt); > + return 1; > + } > + > if (memcmp(test_buffer, expect, written)) { > pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote '%s', expected '%.*s'\n", > bufsize, fmt, test_buffer, written, expect); > -- > 2.17.1 >
-- With Best Regards, Andy Shevchenko
| |