Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting required buffer length with secure _vsnprintf_s

I'm trying to update some "legacy" code to comply with the latest security updates to MSVC, and am facing some trouble migrating from _vsnprintf to _vsnprintf_s.

In particular, I was calling _vsnprintf with a null buffer and zero for the count/length, getting the result, allocating a buffer of the needed size (return value + 1), and then calling _vsnprintf again with the newly-allocated buffer and known-correct size:

size_t length = _vsntprintf(nullptr, 0, mask, params);
TCHAR *final = new TCHAR [length + 1];
_vsntprintf(final, length + 1, mask, params);

This behavior is documented on MSDN:

If the buffer size specified by count is not sufficiently large to contain the output specified by format and argptr, the return value of vsnprintf is the number of characters that would be written if count were sufficiently large. If the return value is greater than count - 1, the output has been truncated.

I'm trying to do the same with _vsnprintf_s, but its documentation does not contain the same. It instead says

If the storage required to store the data and a terminating null exceeds sizeOfBuffer, the invalid parameter handler is invoked, as described in Parameter Validation, unless count is _TRUNCATE, in which case as much of the string as will fit in buffer is written and -1 returned.

Trying it out anyway with the following:

size_t length = _vsntprintf_s(nullptr, 0, 0, mask, params);

This results in a "length" of zero. If you pass in _TRUNCATE (-1) as the count instead, the following assertion fails:

Expression: buffer != nullptr && buffer_count > 0

I presume it is possible to override _set_invalid_parameter_handler and somehow find out what the length should be, but there has to be an easier way?

like image 319
Mahmoud Al-Qudsi Avatar asked Mar 23 '16 22:03

Mahmoud Al-Qudsi


1 Answers

size_t length = _vscprintf(mask, va_list);
TCHAR *final = new TCHAR [length + 1];
_vsntprintf_s(final, length, _TRUNCATE, mask, va_list);
like image 113
TriskalJM Avatar answered Sep 21 '22 02:09

TriskalJM