avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-libc-dev] [RFC] Joerg's new vsprint functions.


From: Theodore A. Roth
Subject: Re: [avr-libc-dev] [RFC] Joerg's new vsprint functions.
Date: Thu, 20 Nov 2003 09:58:44 -0800 (PST)


On Thu, 20 Nov 2003, Joerg Wunsch wrote:

> As Theodore A. Roth wrote:
>
> > A common usage (according to google) is to do something like this:
> >
> >   char *buf;
> >   int length = snprintf (NULL, 0, fmt, ...);
> >   buf = (char *)malloc (length+1);
> >   sprintf (buf, fmt, ...);
> >   ...
> >   free (buf);
> >
> > Basically, using snprintf to determine the desired buffer size prior to
> > allocating the buffer by passing a NULL ptr. This seems like a
> > legitimate thing to be able to do.
>
> That ought to work.  I didn't test it, but effectively, fputc() is
> used, and this function doesn't write anything to the buffer if the
> buffer's size is 0:
>
>         if (stream->flags & __SSTR) {
>                 if (stream->len < stream->size)
>                         *stream->buf++ = c;
>
> If 0 is passed for length, both stream->len and stream->size are 0, so
> the test will fail, and nothing is written.  Consequently, stream->buf
> may be NULL in that case (which is required by the standard, btw.).

Agreed, that looks sane in that circumstance.

>
> An unchecked call to malloc() (as your snippet above indicates) is
> always an error.  This might usually work in a VM environment (such as
> Unix or Win32), but not checking the result is poor coding anyway, and
> not covered by the standard.  Better code usually wraps the calls to
> malloc() in their own function that performs exception handling (in
> the simplest case, by calling abort()).  Sure, in a MCU environment,
> it's not so obvious what to do when running out of memory...

That's not really relevant to this discussion. Replace malloc with a
wrapper, the concept is the same.

>
> > As for penalties, there's three ways to look at it.
> >
> >   1. The caller has to check for NULL before every call to snprintf().
>
> Nope.  Think of situations like this one:
>
>    char mybuf[20];
>    ...
>    (void)snprintf(mybuf, sizeof mybuf, ...);
>
> In this case, it's obvious that the buffer pointer will never be NULL,
> no check is necessary.

Agreed.

> The call to snprintf() (as opposed to sprintf()) is just defensive
> programming so to avoid crashes resulting from buffer overflows, while
> the implementor would usually expect mybuf to be large enough to hold
> the result.  Many people hesitate to use malloc() in an MCU
> environment, so I'd even expect the above to be more frequently used
> there.
>

Agreed, but on the other hand...

If your stack space is limited (like in a multi-tasking system), then
you may not want to have the buffer on the stack and it may not be safe
to put it in the heap. You're going to have to use some kind of malloc.

So... back to the topic.

I don't know what the best thing to do is.

I'm going to just commit the patch for the new interfaces to the 1.0
branch.

Joerg, can you update the documentation to note that it's not safe to
pass a NULL buffer/stream to these functions and close out bug #6141?

Ted Roth




reply via email to

[Prev in Thread] Current Thread [Next in Thread]