|
|
Subscribe / Log in / New account

Vetting the cargo

Vetting the cargo

Posted Jun 10, 2022 20:11 UTC (Fri) by tialaramex (subscriber, #21167)
In reply to: Vetting the cargo by wtarreau
Parent article: Vetting the cargo

Ignoring the rest of the context (which like, it was linked in the article man, if we're doing grumpy old man let's start with JWZ's "In this house we read links")

snprintf(buf, sizeof buf, "%*s", width, string) doesn't "do the job" on its own, we need considerable scaffolding to get to a place where this is the missing ingredient.

The most cheerful option is that we know width is some particular value, and we can construct buf[] as an array nearby of suitable size and then we can just assume this always works.

But if we don't know width, or we're unable to construct buf nearby, perhaps because it's a buffer somebody else owns, we're in a world of pain.

sizeof buf doesn't actually magically tell us how big our buffer is when it's not some nearby array, because this is C (or C++) and so we don't deserve nice things. Instead buf here is a raw pointer, (if we used an array it decays to a pointer for this purpose) and sizeof buf tells us only how big the variable named buf is, which if buf is a pointer will be either 4 or 8 on modern hardware.

When this fails, snprintf can give us a negative answer (unlikely depending on what buf is exactly) or a positive answer. But if it gives us a positive answer we're not done yet. If the positive answer was sizeof buf or greater, it means snprintf calculated all those bytes but the buffer wasn't big enough to actually write them, try again.

So you can end up writing error handling and retry loops here, as well as needing significantly more logic in place of sizeof. Almost makes you wish somebody else did this correctly already so you could just re-use their work, doesn't it?


to post comments

Vetting the cargo

Posted Jun 13, 2022 12:42 UTC (Mon) by int19h (guest, #159020) [Link] (3 responses)

Lest the spirit of joke-ruining pedantry is extinguished, I have to add that in C++, you'd use std::format() for this, and not worry about allocating buffers etc.

Pedantry

Posted Jun 14, 2022 1:28 UTC (Tue) by tialaramex (subscriber, #21167) [Link] (2 responses)

std::format() was added by C++ 20, so, if you're using C++ 98, C++ 03, C++ 11, C++ 14 or C++ 17 this isn't available.

Also, while many modern languages will just cut to the chase, UTF-8 or GTFO, in C++ 20 strings are just containers for arbitrary sequences of values in some implementation defined encoding, so the standard can't say exactly how wide anything is, and although real world implementations probably do what you expect you're assured of nothing for this "width" specification, that's entirely implementation defined. Good luck.

Pedantry

Posted Jun 14, 2022 2:44 UTC (Tue) by Cyberax (✭ supporter ✭, #52523) [Link]

> Also, while many modern languages will just cut to the chase, UTF-8 or GTFO, in C++ 20 strings are just containers for arbitrary sequences of values

I remember that there was a bug filed against the C++ spec because strings were not working when parametrized by doubles due to alignment issues on 32-bit CPUs.

Pedantry

Posted Jun 14, 2022 17:12 UTC (Tue) by madscientist (subscriber, #16861) [Link]

std::format is in C++20 but folks using older C++ compilers can use fmtlib: https://github.com/fmtlib/fmt


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds