Comment by layer8
16 days ago
There is a middle ground that Visual Basic (and then COM) took, with the BSTR type: It’s still a pointer to a zero-terminated char array, but there is a length field immediately preceding the first pointed-to byte. This is still compatible with a C string (assuming no embedded null characters), but BSTR-typed functions can take advantage of the length value.
> This is still compatible with a C string
Strictly speaking, it's not alignment compatible from CString to BSTR unless you declare all strings to be at most 255 characters or the cpu architecture doesn't require aligned access for multi-byte words (like x86). The BSTR alignment must match the alignment of the length word, meaning you can't convert a randomly-aligned C string to BSTR by simply attaching a prefix in-place.
Also, having the length embedded in the value rather than in the pointer makes it impossible to create BSTR (sub)slices without performing a memcpy. Fat pointers do not have this restriction.
A BSTR object is compatible with functions expecting a C string. The other direction obviously never holds, unless the C string is a BSTR to start with.
Yes, there is a trade-off between slices using the same format and having compatibility with C strings. Hence “middle ground”.
You can still use a string-slice type on top of BSTR, it just would be a separate additional type. Note that languages like Java also don’t have a singular type for strings and string slices.
These are great for "data smuggling" attacks where one layer of code assumes the length is 'x' and another layer assumes it is 'y'.
It makes hybrids like this very dangerous for anything even remotely security-adjacent, such as roles, tokens, etc.
This kind of thing caused the CVE-2009-2408 and CVE-2009-2510 "Null Truncation in X.509 Common Name Vulnerability."
FWIW pretty much all Pascals since the 90s use a similar approach.
In Free Pascal for instance, strings are pointers to the first character with a header in a "negative address" containing information about the length, reference count (strings are reference counted and use copy-on-write to avoid passing around copies all the time) and codepage (FP can convert strings between different encodings "transparently").
Nowadays replaced with HSTRING.