Page 1 of 1

Unsafe functions philosophy

Posted: Fri Mar 09, 2012 5:16 am
by Civillian
I noticed that there are functions such as

Code: Select all

char * strnlen(const char *, size_t);
and the entire n-family from C99, where there's a size_t limit.
My question is: isn't this the wrong approach, in the wrong programming language? I'll elaborate...

I perceive a difference between writing user-proof code, and programmer-proof code.
In C, you can do the latter by adding extra validation of input (i.e. pass the size of the array).
But if C itself doesn't provide automatic bounds checking, isn't it against the language's nature to try to emulate it?

Shouldn't the focus shift to making the code user-proof, that is to say sanitize all input at one bottleneck, and keep the functions fast and dumb?

(Of course, we're talking about kernel development, and not of libraries where programmer-proofing could be beneficial.)

Edit: some stupid things.

Re: Unsafe functions philosophy

Posted: Fri Mar 09, 2012 5:55 am
by Solar
Civillian wrote:I noticed that there are functions such as

Code: Select all

char * strnlen(const char *, size_t);
...
...which is typical POSIX "why would I ever need this?" quality, and of a different nature as...
...the entire n-family from C99, where there's a size_t limit.

But if C itself doesn't provide automatic bounds checking, isn't it against the language's nature to try to emulate it?

Shouldn't the focus shift to making the code user-proof, that is to say sanitize all input at one bottleneck, and keep the functions fast and dumb?
If you already have validated your input, and know it cannot exceed the assumed limits, you can use the non-"n" functions ("fast and dumb").

But let's say you are reading lines from a file. You have told the user that lines shouldn't exceed n bytes in length, but you have to cater for bogus input. Now, you could go forth and check if there is a newline within the next n bytes of input, byte-by-byte in a loop, writing byte-by-byte into a buffer as you go, to make sure you don't exceed buffer size.

Or you could simply fgets() (which has a size_t parameter), and let the library handle this.

Afterwards, you know that the line doesn't exceed "n" bytes, and can work "fast & dumb" in the rest of your application.

You see, the "n"-functions are not there to replace the "fast & dumb" originals, they are there to augment them.

Edit: Then, of course, you probably should walk the road of the #include <string>, and be beyond such ponderings. ;-)

Re: Unsafe functions philosophy

Posted: Fri Mar 09, 2012 12:36 pm
by Civillian
Thanks. I'm willing to admit I had the wrong mindset.
I once read a security guide, which urged coders not to use "unsafe functions", in order to avoid buffer overflows and similar problems.

Re: Unsafe functions philosophy

Posted: Sat Mar 10, 2012 1:48 am
by Solar
Yes; you use strncpy() instead of strcpy() if there is any chance of your source buffer exceeding the target buffer. Due to how the average C code is structured, this relates to "most of the time". It takes some discipline and the according mindset to isolate "layers" of code in such a way that you can be certain of sane input in the backend functions, using "non-safe" functions without risking buffer overflow. Hence, always using the "safe" functions is sound general advice, specific exceptions nonwithstanding.

Re: Unsafe functions philosophy

Posted: Sat Mar 10, 2012 9:19 am
by Brynet-Inc
Or you could use OpenBSD's strlcpy/strlcat functions, which are guaranteed to NUL-terminate strings. And unlike strncpy, it's safe to use the sizeof operator.

OpenBSD inserts a .gnu.warning* section for "unsafe" functions, which causes the linker to make noise.

Re: Unsafe functions philosophy

Posted: Sat Mar 10, 2012 2:44 pm
by brain
Brynet-Inc wrote:Or you could use OpenBSD's strlcpy/strlcat functions, which are guaranteed to NUL-terminate strings. And unlike strncpy, it's safe to use the sizeof operator.

OpenBSD inserts a .gnu.warning* section for "unsafe" functions, which causes the linker to make noise.
I always prefer strlcat and friends purely because they guarantee to null terminate strings, in fact in my os's internal cut down string.h I implement strlcat but no strncat or strcat.... imho good practice...

Re: Unsafe functions philosophy

Posted: Sat Mar 10, 2012 8:29 pm
by NickJohnson
Solar wrote:Or you could simply fgets() (which has a size_t parameter), and let the library handle this.
However, as the standard states, fgets() will continue to read into the buffer even past null bytes in the input (it stops only on '\n' and EOF). You won't get a buffer overflow anywhere, but it's behavior you may not expect. If a non-C program stores values in a file as lines and you read them with fgets(), you may be leaving yourself open to null byte injection attacks.