[PATCH v2 2/2] lib/vsprintf: Limit the returning size to INT_MAX

Masami Hiramatsu (Google) posted 2 patches 2 weeks, 1 day ago
There is a newer version of this series
[PATCH v2 2/2] lib/vsprintf: Limit the returning size to INT_MAX
Posted by Masami Hiramatsu (Google) 2 weeks, 1 day ago
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);
Re: [PATCH v2 2/2] lib/vsprintf: Limit the returning size to INT_MAX
Posted by Petr Mladek 2 weeks ago
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
Re: [PATCH v2 2/2] lib/vsprintf: Limit the returning size to INT_MAX
Posted by Masami Hiramatsu (Google) 1 week, 6 days ago
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>