RFR: 8347707: Standardise the use of os::snprintf and os::snprintf_checked
David Holmes
dholmes at openjdk.org
Thu Aug 21 06:06:52 UTC 2025
On Wed, 20 Aug 2025 21:53:11 GMT, Dean Long <dlong at openjdk.org> 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...
>
> src/hotspot/cpu/aarch64/vm_version_aarch64.cpp line 727:
>
>> 725:
>> 726: int desc_len = os::snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "AArch64 ");
>> 727: get_compatible_board(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len);
>
> Suggestion:
>
> int desc_len = os::snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "AArch64 ");
> if (desc_len < CPU_DETAILED_DESC_BUF_SIZE) {
> get_compatible_board(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len);
> }
>
> If there is truncation, _cpu_desc + desc_len will be past the end of the buffer and CPU_DETAILED_DESC_BUF_SIZE - desc_len will be negative in get_compatible_board(), which will cause problems when converted to size_t.
There cannot be truncation here. We are writing a fixed-size string of 8 characters (plus nul-terminator) to a buffer of size 4096.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/26849#discussion_r2289943417
More information about the hotspot-dev
mailing list