Unsafe functions philosophy

Programming, for all ages and all languages.
Post Reply
User avatar
Civillian
Member
Member
Posts: 32
Joined: Tue Feb 21, 2012 3:26 pm

Unsafe functions philosophy

Post 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.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Unsafe functions philosophy

Post 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. ;-)
Every good solution is obvious once you've found it.
User avatar
Civillian
Member
Member
Posts: 32
Joined: Tue Feb 21, 2012 3:26 pm

Re: Unsafe functions philosophy

Post 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.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Unsafe functions philosophy

Post 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.
Every good solution is obvious once you've found it.
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Re: Unsafe functions philosophy

Post 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.
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
User avatar
brain
Member
Member
Posts: 234
Joined: Thu Nov 05, 2009 5:04 pm
Location: UK
Contact:

Re: Unsafe functions philosophy

Post 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...
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Unsafe functions philosophy

Post 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.
Post Reply