Is this legal?

K

Kelvin Moss

Hi all,

Is the following construct legal?

....
snprintf(buffer, buffer_len, "%s+%s", buffer, variable);
....

My buffer is long enough to hold the original buffer, then '+' , and
then 'variable'.
I want to ensure that buffer does not violate the sequence point rule
here.

Thanks.

P.S. - I know snprintf is not a standard function. It is a length safe
version of sprintf provided by my platform.
 
P

pete

Kelvin said:
Hi all,

Is the following construct legal?

...
snprintf(buffer, buffer_len, "%s+%s", buffer, variable);
...

My buffer is long enough to hold the original buffer, then '+' , and
then 'variable'.
I want to ensure that buffer does not violate the sequence point rule
here.

I don't see any sequence point issues in that code.

Thanks.

P.S. - I know snprintf is not a standard function. It is a length safe
version of sprintf provided by my platform.

snprintf is a C99 standard library function.
 
R

Richard Bos

pete said:
I don't see any sequence point issues in that code.

It does not; however, the definitions of both snprintf() in C99, and
sprintf() in C89 and C99, include the line "If copying takes place
between objects that overlap, the behaviour is undefined."

In this case, where buffer is snprintf()ed to its own first characters
(i.e., copied into the exact same spot), I doubt that there will be much
problem in practice; but then again, in this case, I see little reason
not to use strncat() instead, which will be properly defined and will
not lead others into assuming either that you don't know your C or that
using snprintf() is defined where it is not.
In the more general case, where buffer could be snprintf()ed onto
itself, but shifted a bit, I could easily see the result to be
variations on the banananana problem - and you're not guaranteed that
that is the worst that could happen.

Richard
 
A

Andrey Tarasevich

Kelvin said:
Is the following construct legal?

...
snprintf(buffer, buffer_len, "%s+%s", buffer, variable);
...

My buffer is long enough to hold the original buffer, then '+' , and
then 'variable'.
I want to ensure that buffer does not violate the sequence point rule
here.
...
P.S. - I know snprintf is not a standard function. It is a length safe
version of sprintf provided by my platform.
...

If you are talking about some non-standard function, then the only way to answer
your question is to see the specification (or implementation) of that function.
There's are no issues of core language level in the above code (no
sequence-point violations).

If the above function's specification is consistent with the now-standard
'snprintf', then the behavior is undefined. Not because of some sequence-point
issues, but just because the target and source buffers overlap, which is not
allowed by the standard 'snprintf'.
 
M

Michael Wojcik

In this case, where buffer is snprintf()ed to its own first characters
(i.e., copied into the exact same spot), I doubt that there will be much
problem in practice; but then again, in this case, I see little reason
not to use strncat() instead, which will be properly defined and will
not lead others into assuming either that you don't know your C or that
using snprintf() is defined where it is not.

I think strncat is the wrong solution here:

- Kelvin says the buffer is long enough to hold the data being
written to it. If that's generally true, then strcat would suffice.
This is a nit, as strncat would still work, and is no worse than
strcat (unlike strncpy versus strcpy).

- strncat needs to be told the maximum number of characters to
write, not the maximum number of characters in the result. Thus to
use it correctly, the code must know the length of the contents of
buffer, so it can subtract that from buffer_len to provide the
length argument for strncat.
Given that, there's no need to have strncat search for the end
of those contents; just add the length of the contents to buffer.

- Heathfield's Principle of String Copying applies: if you're going
to copy strings, and truncation might occur, it's usually better to
detect that and take an appropriate action.
Given that, you might as well know the length of the contents of
buffer and variable ahead of time.

So:

size_t buf_data_len = strlen(buffer), var_data_len = strlen(variable);
if (buffer_len < buf_data_len + var_data_len + 2)
return SOME_ERROR;
buffer[buf_data_len] = '+';
memcpy(buffer + buf_data_len + 1, variable, var_data_len + 1);

If Kelvin (or anyone else) needs to do this sort of thing frequently,
it might be worth writing a general-purpose functions to do string
composition, appending to a given buffer of given size. (It might
take a variable argument list, though for type-checking purposes I'd
be tempted to just have it take, say, three source string arguments,
any of which would be ignored if null.)

--
Michael Wojcik (e-mail address removed)

Company Secretary Finance Manager
1) Half-grey haired executives.
2) Must be waist-deep in their field of activities.
3) Must be having the know-how and the do-how of the latest
developments in their respective fields.
-- from "Appointments Vacant" section of Business India
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top