Forums

snprintf return value

Started by pozz December 10, 2018
On 12/12/18 7:09 pm, David Brown wrote:
> On 12/12/18 00:34, Clifford Heath wrote: >> On 12/12/18 3:41 am, Phil Hobbs wrote: >>> On 12/10/18 4:49 PM, Clifford Heath wrote: >>>> On 10/12/18 9:20 pm, pozz wrote: >>>>> The return value of snprintf() is useful if you want to dynamically >>>>> reallocate the buffer so it can store all the string. In my case I >>>>> would prefer to truncate the string at the end of the static buffer. >>>> >>>> I'd be seriously asking yourself why you prefer that. >>>> Arbitrary unexpected truncation of data should not be tolerated. >>>> >>>> Clifford Heath. >>> >>> Well, overrunning a buffer is a bug, so it's just a choice of which >>> type of misbehaviour you prefer. If I'm writing to some logfile, for >>> instance, truncating the message is a lot better than overwriting memory! >> >> Right, overflow protection is important. So is data integrity. >> >> So make sure you have a big enough buffer for your data, possibly by >> truncating the data before you snprintf(), or by using %.23s or the >> like. Either way you should handle truncation *deliberately*, not by >> simply clamping to a buffer length. >> > > Not all data is equally valuable. And not all data is of a size that > you know you can handle fully. I have no idea what the OP's original > needs are here, but a prime example is, as Phil said, a log file. Often > the details of what are in the log file are not critical - but avoiding > buffer overruns or limiting the bandwidth used /is/ critical. So > techniques like truncation or rate limiting are entirely reasonable here.
And as long as that's deliberate, that's fine. But the OP's code was appending some number of strings to some buffer. It looked far less deliberate than it ought, though the effect may be as intended. It also splits the buffer-bounds check into many pieces, so any slip fails the whole thing. We used to have a printf that took a putchar function as argument. You could pass one that filled a buffer with truncation. Even easier now that C++ supports lambda closures. Clifford Heath.
Clifford Heath wrote:
> On 12/12/18 3:41 am, Phil Hobbs wrote: >> On 12/10/18 4:49 PM, Clifford Heath wrote: >>> On 10/12/18 9:20 pm, pozz wrote: >>>> The return value of snprintf() is useful if you want to dynamically >>>> reallocate the buffer so it can store all the string. In my case I >>>> would prefer to truncate the string at the end of the static buffer. >>> >>> I'd be seriously asking yourself why you prefer that. >>> Arbitrary unexpected truncation of data should not be tolerated. >>> >>> Clifford Heath. >> >> Well, overrunning a buffer is a bug, so it's just a choice of which >> type of misbehaviour you prefer.� If I'm writing to some logfile, for >> instance, truncating the message is a lot better than overwriting memory! > > Right, overflow protection is important. So is data integrity. > > So make sure you have a big enough buffer for your data, possibly by > truncating the data before you snprintf(), or by using %.23s or the > like. Either way you should handle truncation *deliberately*, not by > simply clamping to a buffer length. > > Clifford Heath.
SO it seems you can have both in this case - if said buffer is truncated you can detect that and reallocate. That being said, prevention is better, IMO - don't set it up to where it can overrun nor be truncated. If you have a variation on %s in there, length-check the string. All other cases should enable the use of like %32.23lf to limit things. The one nasty thing about using a static bnuffer is that you'd need to be able to test it thoroughly and any "reallocation" would require a recompile. -- Les Cargill
Am 10.12.18 um 11:32 schrieb pozz:
>> Keep in mind that snprintf can even return negative values as error >> codes. > > Could you provide a test case for a negative return value from snprintf()? >
The standard allows negative return values only for encoding errors. So for typical systems (i.e. sizeof(char) < sizeof(int), wchar_t is Unicode code points), a %c with an argument outside the range of char should work. Or a %lc with an argument that is not a Unicode code point. Or a %ls with an argument that is an array containing values that are not valid Unicode code points. Philipp