Why C standards contain many unsafe functions, which are useless? - c

Why C standards contain many unsafe functions, which are useless (in good programs them don't use) and harmful, for example getchar? Why C standard doesn't contain instead of them the useful functions, for example getch, and getche? It is only one of many examples...
UPD
I confused: gets instead of getchar.

Do you mean gets? To not break old programs. The road to obsoleteness is long.
And besides, it has been deprecated.

gets is deprecated in C99 and has been removed in C11.
C11(ISO/IEC 9899:201x) Forward/6
removed the gets function ()

You can't implement getch() [reading without buffering] on a teletype (terminal that looks like a typewriter). Or any type of terminal where the data is stored in the terminal until you hit enter.
There are functions that do this sort of things, but remember that C is a language that is supposed to "run on anything".
gets was part of the standard library many years ago, so it has to stay - otherwise, old code won't compile, and a lot of people like to use old code (because it's a lot of work to fix up 1000000 lines of messy code that used to work!)

Related

Use of getch function and gets and puts functions

Experts I've doubts in gets(),puts() and getch().
Why do we use gets() and puts() when we have scanf() and printf()?
What is the use of getch().
Please explain this in simple language because I'm a beginner.
THank you in advance. :)
gets doesn't exist anymore (except in outdated environnments such as the infamous TurboC), use fgets instead.
fgets reads one line of text from a file including from the terminal (standard output)
puts writes one line of text to the terminal (standard output)
fputs writes one line of text to a file, including the terminal (standard output)
getch reads on character from the standard input (terminal)
printf and friends allow you to print formatted output
scanf and friends allow you to read formatted input.
Why do we use gets() and puts() when we have scanf() and printf()?
We don't use gets(), the function was so poorly designed that it was flagged obsolete 18 years ago and finally completely removed from the C language 6 years ago. If someone taught you to use gets(), you need to find a more updated source of learning. See What are the C functions from the standard library that must / should be avoided?.
puts(str) is only used as a micro-optimization of printf("%s", str). puts() is traditionally ever so slightly faster than printf(), since it doesn't need to parse a format string. Today, this performance benefit is a non-issue.
However, puts() is much safer than printf(). You can write bad code like printf("%s", pointer_to_int) and it might compile without warnings. But puts(pointer_to_int) will never compile without warnings/errors.
Generally, most of stdio.h is dangerous and unsafe because of the poor type safety. It is avoided in professional, production-quality code. For student/hobbyist purposes, printf/scanf are however fine.
What is the use of getch()
getch() was a non-standard extension to C, which allowed programs to read a character from stdin without echoing the typed character to stdout (the screen).
This function was popular back in the days of MS DOS when Borland Turbo C was the dominant compiler. Because Turbo C had it, some other compilers also started supporting it together with the non-standard conio.h library. We're talking early 1990s.
You shouldn't use this function in modern C programming.
(Though it is possible to implement it yourself with various API calls, as in this example for Windows.)

Get_s function not working

My book says the get_s() function is a better alternative to the gets() function, which is deprecated and should not be used. But, when I try to use the get_s() function it always gives me an error:
undefined reference to gets_s
This page says something about the gets_s, function that I didn't really understand about it being defined in the ISO/IEC 99. Shouldn' t it work with all the compilers? I'm pretty sure I'm using a very recent version of the MinGW compiler.
How should I use this function? Is using the gets() or scanf() (instead of scanf_s()), or fgets() over fgets_s(), not good?
yes you are right #bumblebee
The gets() function does not perform bounds checking, therefore this function is extremely vulnerable to buffer-overflow attacks. It cannot be used safely (unless the program runs in an environment which restricts what can appear on stdin). For this reason, the function has been deprecated in the third corrigendum to the C99 standard and removed altogether in the C11 standard. fgets() and gets_s() are the recommended replacements.
Never use gets().
source: http://en.cppreference.com/w/c/io/gets
check weather you included the corresponding header. and one more thing u have to see is that weather you c comiler version is an updated version or the old version that can also create a problem.. so try in a c11 standard ,or a c11 online compiler
During early 90s or so, gets() was found to be flawed by design since it would keep reading data forever until it found the end of a string, which meant it could cause buffer overflows either accidentally or through security exploits.
Therefore gets was flagged as an obsolescent function in the C99 standard. Meaning that from the year 1999, people were warned that it should not be used.
The function was removed entirely from the language in the C11 standard, meaning that there was a very generous transit period of no less than 12 years to fix legacy code. It was replaced by gets_s, as a safe alternative to be used when porting old code to C11. It takes the buffer size as second parameter.
However, gets_s should only be used for such C11 porting reasons, if at all. gets_s is part of the optional bounds-checking interface in C11 and compilers need not implement it. The C11 standard recommends to use fgets instead:
Recommended practice
The fgets function allows properly-written
programs to safely process input lines too long to store in the result
array. In general this requires that callers of fgets pay attention to
the presence or absence of a new-line character in the result array.
Consider using fgets (along with any needed processing based on
new-line characters) instead of gets_s.
Note that gets_s has little to do with the non-standard Visual Studio compiler, even though that compiler happens to support this function, just as the standard conforming compilers that support the bounds-checking interface (__STDC_LIB_EXT1__) do.

Why there is so many functions in string.h library that are "not recommended for use"?

There is something I try to understand about C origins, why there are functions that are not recommended for use in most of SO questions. Like strtok or strncpy, they are simply not safe to work with. Evrywhere I see recomendations to write my own implementation. Why wouldn't the standard change strncpy for example to BSD strlcpy, but is left instead with these "monsters"?
C is a product of the early 1970s, and it shows. Many of the iffier library functions were written when the C user community was very small and limited to academia, most of whom were experienced programmers.
By the time the first standard was released in 1989, those original library functions were already entrenched in 10 to 15 years' worth of legacy code (not the least of which was the Unix operating system and most of its tools). The committee in charge of standardization was loath to break the existing codebase, so those functions were incorporated into the standard pretty much as-is; all that really changed was adding prototype syntax to the declarations and changing char * to void * where necessary (malloc, memcpy, memset, etc.).
AFAIK, only one library function has actually been removed from the language since standardization - gets. The mayhem caused by that one library call is scarier than the prospect of breaking what is by now almost 40 years' worth of legacy code.
There is a LOT of legacy "C" and "C++" code out there. If they removed all the "unsafe" functions from the "C" runtime libraries, it would be prohibitive for many developers to upgrade their compilers because all the old code wouldn't build any more.
Sometimes they will give "deprecated" compiler messages (MSFT is fond of this) so you will find and change to using the new, safer functions.
New code should use the "safe" functions, of course, but many of us are stuck with old compilers and legacy code to maintain :)
They still exist because of historical ancestral relationship with the "old system" / "codes" that still use them - i.e. to support "Backward Compatibility"
Own implementation is suggested to make the programmer use their own logic at their own risk as no one can know much better about their environment then the programmer himself, as for example, strtok is not thread safe.
It's all just dogma. Use the functions just be aware that they're indifferent to your goals in that they might not work in all circumstances (ie strtok and multi-threading) or they expect conditions to be caught before/after usage (ie strncpy and missing termination characters).

Can stdio be used while coding for a Kernel...?

I need to build a OS, a very small and basic one, with actually least functionality, coded in C.
Probably a CUI OS which does some memory management and has at least a text editor and a calculator, its just going to be a experimentation about how to make a code that has full and direct control over your hardware.
Still I'll be requiring an interface, that will need input/output functions like printf(&args), scanf(&args). Now my basic question is should I use existing headers or go for coding actually from scratch, and why so ?
I'd be more than very thankful to you guys for and help.
First, you can't link against anything from libc ... you're going to have to code everything from scratch.
Now having worked on a micro-kernel myself, I would not use the actual stdio headers that come with libc since they are going to be cluttered with a lot of extra information that will be either irrelevant for your OS, or will create compiler errors due to missing definitions, etc. What I would do though is keep the function signatures for these standard functions the same ... so in the end you would have a file called stdio.h for your OS, but it would be a very stripped down header file with the basic minimum requirements for your needs, and only having the standard I/O functions you need, with the correct standard signatures.
Keep in mind on the back-end, i.e., in your stdio.c file, you're going to have to point these functions to a custom console-driver or some other type of character drive for your display. Either that, or you could just use them as wrappers for some other kernel-level display printing routine. You are also going to want to make sure that even though you may use a #include <stdio.h> directive in your other OS code modules to access these printing functions, you do not link against libc. This can be done using gcc -ffreestanding.
Just retarget newlib.
printf, scanf, etc relies on implementation specific funcions to get a single char or print a single char. You can then make your stdin and stdout the UART 1 for example.
Kernel itself would not require the printf and scanf functions, if you do not want to keep the kernel in kernel mode and work the apps you have planned for. But for basic printf and scanf features, you can write your own printf and scanf functions, which would provide basic support for printing ans taking input. I do not have much experience on this, but you can try make a console buffer, where the keyboard driver puts the read in ASCII characters (after conversion from scan codes), and then make the printf and scanf work on it. I have one basic implementation were i have wrote a gets instead of scanf and kept things simple. To get integer output you can write an atoi function to convert the string to a number.
To port in other libraries, you need to make the components which the libraries depend on. You need to make the decision if you can code in those support in the kernel so that the libraries could be ported in. If it is more difficult then coding some basic input output functions i think won't be bad at this stage,

Safer Alternatives to the C Standard Library

The C standard library is notoriously poor when it comes to I/O safety. Many functions have buffer overflows (gets, scanf), or can clobber memory if not given proper arguments (scanf), and so on. Every once in a while, I come across an enterprising hacker who has written his own library that lacks these flaws.
What are the best of these libraries you have seen? Have you used them in production code, and if so, which held up as more than hobby projects?
I use GLib library, it has many good standard and non standard functions.
See https://developer.gnome.org/glib/stable/
and maybe you fall in love... :)
For example:
https://developer.gnome.org/glib/stable/glib-String-Utility-Functions.html#g-strdup-printf
explains that g_strdup_printf is:
Similar to the standard C sprintf() function but safer, since it calculates the maximum space required and allocates memory to hold the result.
This isn't really answering your question about the safest libraries to use, but most functions that are vulnerable to buffer overflows that you mentioned have safer versions which take the buffer length as an argument to prevent the security holes that are opened up when the standard methods are used.
Unless you have relaxed the level of warnings, you will usually get compiler warnings when you use the deprecated methods, suggesting you use the safer methods instead.
I believe the Apache Portable Runtime (apr) library is safer than the standard C library. I use it, well, as part of an apache module, but also for independent processes.
For Windows there is a 'safe' C/C++ library.
You're always at liberty to implement any library you like and to use it - the hard part is making sure it is available on the platforms you need your software to work on. You can also use wrappers around the standard functions where appropriate.
Whether it is really a good idea is somewhat debatable, but there is TR24731 published by the C standard committee - for a safer set of C functions. There's definitely some good stuff in there. See this question: Do you use the TR 24731 Safe Functions in your C code?, which includes links to the technical report.
Maybe the first question to ask is if your really need plain C? (maybe a language like .net or java is an option - then e.g. buffer overflows are not really a problem anymore)
Another option is maybe to write parts of your project in C++ if other higher level languages are not an option. You can then have a C interface which encapsulates the C++ code if you really need C.
Because if you add all the advanced functions the C++ standard library has build in - your C code would only be marginally faster most times (and contain a lot more bugs than an existing and tested framework).

Resources