From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
The return value of vsnprintf() can overflow INT_MAX and return
a minus value. In the @size is checked input overflow, but it does
not check the output, which is expected required size.
This should never happen but it should be checked and limited.
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
lib/vsprintf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 32a164e2adf4..ea5e1d22ff8f 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -2985,7 +2985,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt_str, va_list args)
}
/* the trailing null byte doesn't count towards the total */
- return str-buf;
+ return WARN_ON_ONCE(str - buf > INT_MAX) ? INT_MAX : str - buf;
}
EXPORT_SYMBOL(vsnprintf);
On Fri 2026-03-20 12:54:57, Masami Hiramatsu (Google) wrote: > From: Masami Hiramatsu (Google) <mhiramat@kernel.org> > > The return value of vsnprintf() can overflow INT_MAX and return > a minus value. In the @size is checked input overflow, but it does > not check the output, which is expected required size. > > This should never happen but it should be checked and limited. Great catch! > --- a/lib/vsprintf.c > +++ b/lib/vsprintf.c > @@ -2985,7 +2985,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt_str, va_list args) > } > > /* the trailing null byte doesn't count towards the total */ > - return str-buf; > + return WARN_ON_ONCE(str - buf > INT_MAX) ? INT_MAX : str - buf; Is it guaranteed that the pointer arithmetic will be a big enough unsigned number type? I would rather do a cast to be on the safe side, for example: return WARN_ON_ONCE((size_t)(str - buf) > INT_MAX) ? INT_MAX : str - buf; or even use a variable to make it better readable: size_t ret_size; ret_size = str - buf; if (WARN_ON_ONCE(ret_size > INT_MAX)) ret_size = INT_MAX; return ret_size; Best Regards, Petr
On Fri, 20 Mar 2026 17:51:48 +0100 Petr Mladek <pmladek@suse.com> wrote: > On Fri 2026-03-20 12:54:57, Masami Hiramatsu (Google) wrote: > > From: Masami Hiramatsu (Google) <mhiramat@kernel.org> > > > > The return value of vsnprintf() can overflow INT_MAX and return > > a minus value. In the @size is checked input overflow, but it does > > not check the output, which is expected required size. > > > > This should never happen but it should be checked and limited. > > Great catch! > > > --- a/lib/vsprintf.c > > +++ b/lib/vsprintf.c > > @@ -2985,7 +2985,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt_str, va_list args) > > } > > > > /* the trailing null byte doesn't count towards the total */ > > - return str-buf; > > + return WARN_ON_ONCE(str - buf > INT_MAX) ? INT_MAX : str - buf; > > Is it guaranteed that the pointer arithmetic will be a big enough > unsigned number type? > > I would rather do a cast to be on the safe side, for example: > > return WARN_ON_ONCE((size_t)(str - buf) > INT_MAX) ? INT_MAX : str - buf; OK. > > or even use a variable to make it better readable: > > size_t ret_size; > > ret_size = str - buf; > if (WARN_ON_ONCE(ret_size > INT_MAX)) > ret_size = INT_MAX; > return ret_size; Ah, Indeed. Let me do this. Thanks! > > Best Regards, > Petr -- Masami Hiramatsu (Google) <mhiramat@kernel.org>
© 2016 - 2026 Red Hat, Inc.