RFC: 8347707: Standardise the use of os::snprintf and os::snprintf_checked

David Holmes david.holmes at oracle.com
Mon Aug 4 02:20:38 UTC 2025


Seems there is no real interest in a pre-discussion so I will make the 
PR non-draft.

David

On 25/07/2025 11:54 am, David Holmes wrote:
> This is a proposal to standardize on the use of os::snprintf and 
> os::snprintf_checked across the hotspot code base, and to disallow use 
> of the C library variants. (It does not touch use of jio_printf at all.)
> 
> From: https://bugs.openjdk.org/browse/JDK-8347707
> 
> The platform `snprintf/vsnprintf` returns -1 on error, else if the 
> buffer is large enough returns the number of bytes written (excluding 
> the null byte), else (buffer is too small) the number of characters 
> (excluding the terminating null byte) which would have been written to 
> the final string if enough space had been available. Thus, a return 
> value of size or more means that the output was truncated.
> 
> To provide a consistent approach to error handling and truncation 
> management, we provide `os::xxx` wrapper functions as described below 
> and forbid the use of the library `::vsnprintf` and `::snprintf`.
> 
> The potential errors are, generally speaking, not something we should 
> encounter in our own well-written code:
> 
> - encoding error: not applicable as we are not using extended character 
> sets
> - invalid parameters (null buffers, specifying a limit > size of the 
> buffer [Windows], things of this nature)
> - mal-formed formatting directives
> - overflow error (POSIX) if the required buffer size exceeds INT_MAX (as 
> we return `int`).
> 
> As these should simply never occur, we handle the checks for -1 at the 
> lowest-level (`os::vsnprintf`) with an assertion, and accompanying 
> precondition assertions.
> 
> The potential clients of this API then fall into a number of camps:
> 
> 1. Those who have sized their buffer correctly, don't need the return 
> value for subsequent use, and for whom truncation (if it were possible) 
> would be a programming error.
> 
> For these clients we have `void os::snprintf_checked` - which returns 
> nothing and asserts on truncation.
> 
> 2. Those who have sized their buffer correctly, but do need the return 
> value for subsequent operations (e.g. chains of `snprintf` where you 
> advance the buffer pointer based on previous writes), but again for whom 
> truncation should never happen.
> 
> For these clients we have `os::snprintf`, but they have to add their own 
> assertion for no truncation.
> 
> 3. Those who present a buffer but know that truncation is a possibility, 
> but don't need to do anything about it themselves, and for whom the 
> return value is of no use.
> 
> These clients also use `os::snprintf_checked`. The truncation assertion 
> can be useful for guiding buffer sizing decisions, but in product mode 
> truncation is not an error.
> 
> 4. Those who present a buffer but know that truncation is a possibility, 
> and either need to handle it themselves, or else need to use the return 
> value in subsequent operations.
> 
> These clients are also directed to use `os::snprintf`.
> 
> In summary we provide the following API:
> - `[[nodiscard]] int os::vsnprintf` is the building block for the other 
> methods, it:
>    - asserts on precondition failures
>    - asserts on error
>    - guarantees null-termination in the case of unexpected errors (as 
> the standards are still unclear on that point
>    - is declared `[[nodiscard[]]` so that callers cannot ignore the 
> return value (they can explicitly cast to `void` to indicate they dn't 
> need it)
> - `void os::snprintf_checked`
>    - calls `os::vnsprintf`` so asserts on errors
>    - asserts on truncation
> - [[nodiscard]] int os::snprintf
>    - calls `os::vnsprintf`` so asserts on errors
> 
> In terms of the effects on the existing code we:
> - Change callers of `::snprintf`/`os::snprintf` that ignore the return 
> value and ensure the buffer is large enough to use `os::snprintf_checked`
>    - those that allow truncation to happen must use `os::snprintf`.
> - Change all callers of `::snprintf`/`os::snprintf` that use the return 
> value to use `os::snprintf`, plus any additional assertions needed
> - Change the 9 callers of `os::snprintf_checked` that do use the return 
> value, to use `os::snprintf` with their own assertions added
> - Callers of `os::vnsprintf` are adjusted as needed
> 
> There is a draft PR comprising of multiple dependent commits so that you 
> can view things in stages. There has been a suggestion to integrate this 
> in a staged way under different JBS issues to make reviewing easier. 
> There are 46 modified files. The bulk of changes replace calls to 
> snprintf/os::snprintf with calls to os::snprintf_checked.
> 
> https://github.com/openjdk/jdk/pull/26470
> 
> Comments welcomed.
> 
> Thanks,
> David
> 



More information about the hotspot-dev mailing list