On Fri, May 24, 2019 at 07:22:07PM +0700, Oleg Chumanov wrote:
> First of all, I really want to thank you for your files.
> 
> However, Can you show me an example of these:
> 
> > makes it easier to perform error
> > recovery in the caller. For example, the caller may wish to
> > reallocate the buffer and retry.
> >
> > That would make it a bit harder to do error recovery since you'd
> > need to compute the required length
> 
> I mean, I can do something like this:
> 
>       offset = 0;
>       while ((n = olegcpy(buf + offset, str + offset, buf_size - offset))) {
>               offset       = buf_size - 1;
>               buf_size += n;
>               buf           = realloc(buf, buf_size);
>       }

Of course, you could, but you are totally missing the point of 
strlcpy/strlcat.

Look, the basic idea is that developers make mistakes.

All of them.

Including *you*.

Not all the time, but once is enough, especially where buffer overflows
are concerned.

Your proposed interface (which I renamed olegcpy) is more complex to use 
than regular strlcpy.

Look, you *are* doing pointer arithmetic in your loop.

Oh, btw, your code is wrong... you forgot to check that buf_size didn't
overflow (unlikely, I know), and you *also* forgot to check that realloc
did work.

That's not your point ?

Actually, it *is*. You had to devote brain cells to thinking about your
very smart loop, so you missed a few trivial points.

That's what strlcpy is all about. It's a PLAIN SIMPLE interface designed
for ACTUAL PEOPLE.

Compare that with strlcpy

while (1) {
        size_t n = strlcpy(buf, str, buf_size);
        if (n < bufsize)
                break;
        char *newb = realloc(buf, n);
        if (!newb) {
                free(buf);
                /* oh hey, that's an error */
                exit(1);
        }
        buf = newb;
        buf_size = n;
}

Oh, hey, I didn't forget to test for actual errors. Because the code
is simpler.

So, yes, I copy the same string twice, once in a blue moon.
Guess what ? FOR REAL PROGRAMS IT DOESN'T MATTER.

*IF* your buffer sizes are carefully chosen, you won't reallocate them
THAT often (especially because the smart thing to do is to devote energy
to actually track average buffer sizes and reuse buffers so you don't
reallocate all the time).

So, in reality, I won't ever realloc *exactly* what strlcpy gives me.
My code looks more like this usually:

while (1) {
        size_t n = strlcpy(buf, str, buf_size);
        if (n < bufsize)
                break;
        while (n > bufsize)
                bufsize <<= 1U;
        char *newb = realloc(buf, bufsize);
        if (!newb) {
                free(buf);
                /* oh hey, that's an error */
                exit(1);
        }
        buf = newb;
}

and I do *love* strlcpy and strlcat because they're simple enough to use
that I can spend my time concentrating on stuff that actually matters,
without too much risk at introducing more bugs in existing programs.




"Premature optimization is the root of all evil" (Don E. Knuth)

Reply via email to