The reason is simple.
snprintf is easy to use.
Let me ask you a question. If checking the arguments before calling
sprintf is so easy, why did only 1 on 20 programs do so? Why did they
all overflow? Why were 4 people kept busy for almost a year fixing
buffer overflows?
Why, perhaps 10 years after buffer overflows became well known, did
people persist in not checking the buffer sizes before calling
sprintf?
Let me give you an example of what you suggest:
if (strlen(a) + 1 + 10 + 3 + 1 + 10 + 4*sizeof(long) + 1 + strlen(b) +
1 + strlen(c) + 2 >= sizeof buf);
sprintf(buf, "%s %d see %d %lx %s %s\n", a, i, j, p,
b, c);
else
goto bail; /* I really just wanted to truncate the string... */
The reason is simple.
If it isn't easy to write secure code, people will not write secure
code.
And anyways, in 99% of the cases a truncation is desirable, because
anything else is an error we don't know how to deal well with. I have
run into very few cases where truncation wasn't acceptable behaviour.