I'm running a CTF and I am currently writing a problem that exploits C's gets function. I understand that the function is deprecated and dangerous and I would never use it in any other circumstance. Unfortunately, gcc compiles my code and when I run the binary when the gets function is hit, I get a friendly error message:
warning: this program uses gets(), which is unsafe.
This would normally be great, because it warns you that gets is unsafe, but unfortunately, in my CTF, I think that this error message makes the problem a bit too easy. Do you know how I would go about disabling this warning? Thanks!
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.3 (clang-1103.0.32.62)
Target: x86_64-apple-darwin19.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Note: I just realized that your question title seems to be misplaced - The warning you got is from macOS about executing a program which uses gets(). It has nothing to do with the compilation by using GCC.
:-/ Any way, I let my answer alive for reference.
Just as comment: I googled a bit about what you are looking for, but there seems to be no reliable way to disable this warning when executing the program. One suggested rebuilding /usr/lib/libSystem.B.dylib without any result or experience if it indeed works, but I personally think this a bit too extreme and even can be harmful. - I do not recommend this technique.
If you really want to create an exploit program, try to rebuild gets() by a costum-made function and name the function a bit different, like f.e. gets_c(). This should be a workaround to disable this warning from macOS.
Old answer (regarding GCC itself):
First of all, you seem to be using a C99 or C89/C90-compliant compiler or alternatively compile with std=c99 or std=c89/std=c90 option, because only compilers conform to standards preceding C11 warn about gets() being deprecated.
ISO/IEC removed the gets() function in C11. If you would compile with a C11 or newer standard-compliant compiler, you would get an error about the implicit declaration of gets() when using it in the code instead:
"error: implicit declaration of function 'gets'; did you mean 'fgets'? [-Werror=implicit-function-declaration]"
If you want to suppress the warning at compilation, use the -Wno-deprecated-declarations option at compiling to disable the diagnostic for deprecated declarations.
From the GCC online docs:
-Wno-deprecated-declarations
Do not warn about uses of functions, variables, and types marked as deprecated by using the deprecated attribute. (see Function Attributes, see Variable Attributes, see Type Attributes.)
Source: https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Warning-Options.html
If you want to embed the suppression of the warning in your code use the approach used in David´s deleted answer implementing a suppression for -Wno-deprecated-declarations by using #pragma:
char str[256];
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
gets(str);
#pragma GCC diagnostic pop
Related
I am trying to compile a C source code to a machine code using an ubunto terminal
My tutor instruction was to use the following command:
running clang myprogramm.c -std=c11
Why shall I use the keyword -std=c11 and what is the difference to using just
clang myprogramm.c
Using std= options is required by your tutor (I'm divinig her motives, I'm particularly good at this!) because she wants to make sure you stay away from all those nifty Clang features that turn the accepted language from C to A LANGUAGE SUPERFICIALLY LOOKING LIKE C BUT ACTUALLY A DIFFERENT LANGUAGE NOT SUPPORTED BY OTHER C COMPILERS.
That is more than just additional library functions. It include syntax changes that break the grammar of Standard C, as defined by ISO. A grasshopper should not use these while learning. Using -std=c11 makes sure Clang either warns about or even rejects, with an error, such constructs.
When to specify the standard? Whenever you use the compiler. It is never a good idea to let the compiler just use whatever it wants.
If someone tries to use a compiler that is too old, then they will get a warning or error, and they will understand why the compile fails.
If a code contributor (maybe even yourself!) tries to add code using features that are too new, their code will be rejected. That's very important if you intend to keep compatibility with an older standard.
By explicitly stating the standard, using new features or extensions are a choice and don't happen by accident.
How to make a compilation successful for a program with a variable length array?(currently, Showing error : Variable sized array). I am using gcc in linux. How to make compiler compatible to c99 standard ? PLease help me in this. THanks in advance.
How to make compiler compatible to c99 standard?
By default, the compiler defaults to the most compatible version of C version is installed. Do define the compilation version explicitly, compile the program with the following command-line:
$ gcc -std=c99 -o my_program my_program.c
By defining the -std=c99, the compiler will be using C99 standard.
Edit: If you're still getting the warning and not the error, then you need to provide your code to know what exactly is wrong.
"How to make a compilation successful for a program with a variable length array? (currently, Showing error : Variable sized array)."
Usually it isn't an error to compile a code with a VLA unless you compile with -Werror flag.
The diagnostic you get is high-probably "only" a warning that you use a VLA inside of it, which is risky.
Thus, the compiler informs you about that.
So, you indeed can compile a program with VLAs without any error.
If you got errors they must belong to anything else. We can't find those out since you showed no specific code.
Take a look at this question of mine, not so long ago (even if it is for Clang, it covers the same topic as the answers suggest that a compiler is free to complain about whatever it likes):
Why does clang complain about using variable-length arrays with '-std=c99' flag?
All useful information you can find there.
VLAs are not portable. Try to use alternatives, for example dynamically allocated arrays by using malloc().
Related:
malloced array VS. variable-length-array
Is there any overhead for using variable-length arrays?
Is it a good idea to use C99 VLA compared to malloc/free?
"How to make compiler compatible to (the) C99 standard?"
As Rohan in his answer already said, you can use the -std-c99 flag at the invocation of gcc for that. But it probably won't solve your problem to do so.
I want to get rid of all implicit-function-declaration warnings in my codebase. But there is a problem because some functions are
programmed into the microcontroller ROM at the factory and during linking a linker script provides only the function address. These functions are called by code in the SDK.
During compilation gcc of course emits the warning implicit-function-declaration. How can I get rid of this warning?
To be clear I understand why the warning is there and what does it mean. But in this particular case the developers of SDK guarantee that the code will work with implicit rules (i.e. implicit function takes only ints and returns an int). So this warning is a false positive.
This is gnu-C-99 only, no c++.
Ideas:
Guess the argument types, write a prototype in a header and include that?
Tell gcc to treat such functions as false positive with some gcc attribute?
You can either create a prototype function in a header, or suppress the warnings with the following:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
/* line where GCC complains about implicit function declaration */
#pragma GCC diagnostic pop
Write a small program that generates a header file romfunctions.h from the linker script, with a line like this
int rom_function();
for each symbol defined by the ROM. Run this program from your Makefiles. Change all of the files that use these functions to include romfunctions.h. This way, if the linker script changes, you don't have to update the header file by hand.
Because most of my programming expertise was acquired by self-study, I intentionally have become somewhat anal about resolving non-fatal warnings, specifically to avoid picking up bad coding habits. But, this has revealed to me that such bad coding habits are quite common, even from formally trained programmers. In particular, for someone like me who is also anal about NOT using MS Windows, my self-study of so-called platform-independent code such as OpenGL and Vulkan has revealed a WORLD of bad coding habits, particularly as I examine code written assuming the student was using Visual Studio and a Windows C/C++ compiler.
Recently, I encountered NUMEROUS non-fatal warnings as I designed an Ubuntu Qt Console implementation of an online example of how to use SPIR-V shaders with OpenGL. I finally threw in the towel and added the following lines to my qmake .PRO file to get rid of the non-fatal-warnings (after, first, studying each one and convincing myself it could be safely ignored) :
QMAKE_CFLAGS += -Wno-implicit-function-declaration
-Wno-address-of-packed-member
[Completely written due to commends]
You are compiling the vendor SDK with your own code. This is not typically what you want to do.
What you do is you build their SDK files with gcc -c -Wno-implicit-function-declaration and and your own files with gcc -c or possibly gcc -o output all-your-c-files all-their-o-files.
C does not require that declarations be prototypes, so you can get rid of the problem (which should be a hard error, not a warning, since implicit declarations are not valid C) by using a non-prototype declaration, which requires only knowing the return type. For example:
int foo();
Since "implicit declarations" were historically treated as returning int, you can simply use int for all of them.
If you are using C program, use
#include <stdio.h>
I saw yet another question about C where the code was using gets(),
and I commented with the usual warning about never using gets() except
when you want to demonstrate how to break security.
This time, I decided to check if my compiler issued a warning about the
use of gets(). Of course I expected it would. Has to, right? Even if
you don’t specify any warnings?
Imagine my surprise when I found that, not only does the compiler not
warn by default, but I couldn’t even figure out how to make it warn!
The compiler in question is gcc 4.7.2 on Debian, and here’s the code I
used:
#include <stdio.h>
int main(void)
{
char s[10];
gets(s);
puts(s);
return 0;
}
Tried gcc g.c. Compiles with no warnings. Runs. Gets a segfault if
you enter too much text.
Tried with all the standard warnings I normally put in a makefile:
gcc -W -Wall -Wno-long-long -Wshadow -Wlarger-than-1000 \
-Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align \
-Wconversion -Waggregate-return -Wmissing-prototypes \
-Wmissing-declarations -Wpadded -Wredundant-decls -Wnested-externs g.c
Same result.
Tried with -std=c11. Even that didn’t generate a warning, which is
pretty weird, considering gets() doesn’t even exist in C11. Tried
c99 too. No warning.
So what’s going on here? Why doesn’t this very widely used compiler warn
me when I use the most deprecated function in the entire C language?
EDIT: Acting on Keith Thompson’s suggestion below, I checked for a
deprecation attribute in stdio.h. It was not there. I then copied the
header file and experimented. Adding either of these strings (which I
found in other headers) to the end of the declaration did generate a
warning:
__attribute_deprecated__
__attribute__ ((__deprecated__))
The warning:
‘gets’ is deprecated (declared at /usr/include/stdiotz.h:632) [-Wdeprecated-declarations]
To summarize the responses I’ve seen so far, it appears that the version
of libc on my system doesn’t include the warning, which does exist in
later versions. This is strange, since the warning has existed in some
form since at least 1996. I vaguely recall that libc has been forked at
least once, so perhaps the warning was left out of one branch
significantly later than in other branches.
I think I will ask on the Debian mailing lists about this, and perhaps
report it as a bug, depending on what I learn.
EDIT 2: I’ve looked at some source code. glibc has had the warning
since 2007 at least, in libio/iogets.c. eglibc 2.13, the one I have,
has exactly the same warning code:
#ifdef _LIBC
link_warning (gets, "the `gets' function is dangerous and should not be used.")
#endif
I suppose _LIBC wasn’t defined when the library was compiled. Why, I
don’t know. I’m not sure what the purpose of _LIBC is.
So, the answer seems to come down to “It’s the library, and for whatever
reason, in their wisdom, the Debian developer responsible for it
compiled it that way.” We may never know why.
Not going to report it as a bug, since I’m using oldstable. Might bring
it up if it’s still that way after my next upgrade.
Thanks, everyone, for your informative responses!
It's not the GCC that includes this warning message, it's the GLIBC.
It's unlikely that you're using too old version of GLIBC: the warning has been around at least since 1996. See the line 67 of this GLIBC code on GitHub for an example (note the date: 15 Dec 1996):
link_warning (gets, "the `gets' function is dangerous and should not be used.")
Most likely you're using a different C library.
I recently realized that I am not even in C99 mode after receiving the compile error
'for' loop initial declarations are only allowed in C99 mode
I found some advice on how to get to C99 via a quick search which has told me to go to Projects -> Properties... But alas, it is greyed out and I am not sure that is even the correct way to fix it (probably not available because my file is not a project, it is a normal source file). I have also seen a lot of similar questions saying to enable C99 mode so I have looked inside the compiler flags menu, but I cannot see anything about C99. I have tried some other flags such as In C Mode, support all ISO C90 programs..., but after I set this flag, I got more errors than I had before which seem to appear whenever the compiler finds comments inside main().
Note: Please don't just say to initialize the counter outside the for loop.
Update: While trying to compile outside of codeblocks with gcc, I tried
gcc -O2 -std=C99 filename.c, but received an error:
unrecognized command line option "-std=C99"
I use 64-bit Windows 7, CodeBlocks10.05, and GNU gcc.
For future reference, type in the flag -std=c99 in settings->compiler->other options which is not case-sensitive, however when compiling in a terminal the flag is case-sensitive. Thanks chris!