On Wed, 20 Aug 2025 22:18:28 GMT, Dean Long <dl...@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/os/aix/os_aix.cpp line 1055:
> 
>> 1053:     if (ebuf != nullptr && ebuflen > 0) {
>> 1054:       os::snprintf_checked(ebuf, ebuflen - 1, "%s, LIBPATH=%s, 
>> LD_LIBRARY_PATH=%s : %s",
>> 1055:                            filename, ::getenv("LIBPATH"), 
>> ::getenv("LD_LIBRARY_PATH"), error_report);
> 
> Suggestion:
> 
>       (void) os::snprintf(ebuf, ebuflen - 1, "%s, LIBPATH=%s, 
> LD_LIBRARY_PATH=%s : %s",
>                            filename, ::getenv("LIBPATH"), 
> ::getenv("LD_LIBRARY_PATH"), error_report);
> 
> This could easily truncate, based on LIBPATH and LD_LIBRARY_PATH.

Yes but again if that happens during testing we need to know and fix the buffer 
size to get the non-truncated values.

> src/hotspot/os/aix/os_aix.cpp line 1097:
> 
>> 1095:   struct utsname name;
>> 1096:   uname(&name);
>> 1097:   os::snprintf_checked(buf, buflen, "%s %s", name.release, 
>> name.version);
> 
> Suggestion:
> 
>   (void) os::snprintf(buf, buflen, "%s %s", name.release, name.version);

See previous replies.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/26849#discussion_r2289995061
PR Review Comment: https://git.openjdk.org/jdk/pull/26849#discussion_r2289996137

Reply via email to