I am using visual studio 2017 .
First I wrote the following code :
void main()
{
printf("abcdefgh %d hjhjh %d", 5, 6);
getch();
}
It ran perfectly fine .
But after that I modified the code to the following :
void main()
{
char abc[100];
strcpy_S(abc, "premraj");
printf("%s", abc);
printf("abcdefgh %d hjhjh %d", 5, 6);
getch();
}
But now I am getting an error with getch stating that "'getch' undefined, assuming extern returning int"
But this new code has been built on the existing code which recognized getch perfectly , how can it not recognize getch the second time ?
I checked out the following question :
getch() is working without conio.h - how is that possible?
which also carried a similar problem but here with modifications only I got this error .
There is an informative answer there by user named "Fatal Error" but still I would like to know about this intriguing phenomenon that is coming in after modifications . What can be the reason behind this ?
P.S : The following was my header file declarations for the first time :
#include <stdio.h>
and the following for the second time :
#include <stdio.h>
#include <string.h>
Once upon a time, if you called a function which the compiler had never heard of, like this:
#include <stdio.h>
int main()
{
int x = foo();
printf("%d\n", foo);
}
Anyway, if you did that, the compiler quietly assumed that foo() was a function returning int. That is, the compiler behaved just as if you had typed
extern int foo();
somewhere before you called foo.
But in, I think, C99, the language was changed. It was no longer legal to call a function you had not explicitly declared. Because there was lots and lots of code out there that was written under the previous set of rules, most compilers did not immediately begin rejecting the old-style code. Some continued to quietly assume that unrecognized functions returned int. Others -- like yours -- began noisily assuming that unrecognized functions returned int, emitting warnings along the lines of "'foo' undefined, assuming extern returning int".
It sounds like your question is that some time ago, your code containing calls to getch() was accepted without warning, but today, you're getting the warning "'getch' undefined, assuming extern returning int". What changed?
One possibility is that your code changed slightly. If your code used to contain the line
#include <conio.h>
somewhere, that file would have contained a declaration along the lines of
extern int getch();
and this would have goven the compiler the declaration that it needed, and you would not have gotten the warning. But if today your code does not contain that #include line, that explain why the warning started cropping up.
It's also possible that your compiler has changed somehow. It's possible you're using a new version of the compiler, that's more fussy, that has gone from quietly assuming, to normally assuming. Or, it's possible that your compiler options have changed. Many compilers can be configured to accept different variants of the language, corresponding to the different versions of the language standards that have been released over the years. For example, if some time ago your compiler was compiling for language standard "C89", but today, it's doing "C99" or "C11", that would explain why it's now being noisy with this warning.
The change in the compiler could be a change in the defaults as configured by a system administrator, or a change in the way you're invoking the compiler, or a change in your project's Makefile, or a change in the language settings in your IDE, or something like that.
A few more points:
getch is not a Standard C function; it's specific to Windows. Your program would be more portable, in general, if you didn't use it. Are you sure you need it? (I know what it's for; what I don't know if there's some other way of keeping your program's output window on the screen after if exits.)
You should get in the habit of declaring main() as int, not void. (void will work well enough, but it's not correct, and if nothing else, you'll get lots of negative comments about it.)
I think there's something wrong with your call to strcpy_S, too,
Related
I had an interview question where the interviewer asked me what error would we get from the below output:
int main()
{
printf("hello world");
return 0;
}
#include <stdio.h>
I answered "no error" and it will display the output.
can anyone help me with this???
Please note"the missing angular brackets is intentionally done by me so dont bother about that"
It depends on the compiler.
Most C compilers will probably accept that code (perhaps with a warning) and produce an executable that prints the expected output.
Under C90 rules, the behavior of the printf call is undefined; it's invalid to call a variadic function with no visible prototype. Variadic functions can have a different calling convention from ordinary functions, and you have to let the compiler know that printf is variadic so it can generate correct code for the call.
Under C99 and later rules, calling any function with no visible declaration (which may or may not be a prototype) is a constraint violation, requiring at least a compile-time warning.
The standard doesn't hint at what happens if you call printf without the required prototype, but in practice most compilers will handle it "correctly".
The missing '\n' at the end of the output means that the program's behavior is undefined if the implementation requires a newline at the end of the output; whether that's required or not is implementation-defined. In any case, adding a newline is a good idea.
The #include <stdio.h> at the end of the source file should be useless but harmless.
I'm assuming that the source file actually contains #include <stdio.h> and not #include stdio.h; the latter would be a syntax error.
(Practically speaking, of course, the #include <stdio.h> should be at the top. In a professional setting, the output is irrelevant, since the program will never survive a code review.)
You will get an error for missing quotes or <> in the filename for the #include. It should be:
#include <stdio.h>
Apart from that, it should compile with a warning about an implicit declaration to printf(). On Clang, it gives me:
test.c:3:5: warning: implicitly declaring library function 'printf' with type 'int (const char *, ...)'
printf("hello world");
^
When your main() function is being declared, the compiler will run into the first line of main() and it will have no idea what printf() is. You will get an error about the compiler complaining about an undeclared function.
Assuming, of course, the missing < and > was a mistake introduced when you copied your question over.
There are two errors here. The first is that the include directive must happen before the code that requires that header information, in this case printf() is declared in stdio.h, and the second is that the filename in the include directive must be enclosed in angle brackets, <>, or quotes, "".
#include <sys/types.h>
//Line 2: typedef unsigned int uint;
//Line 3: typedef unsigned int uint;
int main() {
uint a;
return 0;
}
Given the above C code, it's compiled successfully, for uint is defined in <sys/types.h>. Even though it's not standardized, it's added there for Sys V compatibility, commented in the code.
Uncomment the second line of the above code still results successful compiling. As I understand it's not allowed to redefine one type, confirmed by uncommenting the second and third lines, which will result in one compiling error.
How come the compiler is smart enough to know uint is defined in standard library or user's code? Both gcc and clang give consistent behavior.
Edit:
Linking is not part of the game in this case. The error is reproduced with compile only, i.e (-c option).
Line number is added to reduce confusion.
Edit:
Uncomment the second line of the above code still results successful compiling. As I understand it's not allowed to redefine one type, confirmed by uncommenting the second and third lines, which will result in one compiling error.
I have no idea why I wrote this. Apparently, uncommenting Line 2 and Line 3 doesn't result in compilation error for gcc. Clang gives error for the default compiling options is much more strict and could be tuned by passing some parameters.
Here describes whether multiple typedef is allowed or not, which turns out to be quite complicated. Anyway just try to avoid duplicate typedef.
Repeating a declaration is perfectly valid in C, so if you uncomment both lines as you describe you will not see any error, contrary to what you say.
Having two different declarations for a name would be an error.
Repeating a definition is an error as well, but a typedef is not a definition (despite the def), it is a declaration.
Standard library is also user code, usually written by another user.
Uncomment the second line of the above code still results successful compiling. As I >understand it's not allowed to redefine one type, confirmed by uncommenting the second and third lines, which will result in one compiling error.
On my gcc it does not. (version 4.5.3)
How come the compiler is smart enough to know uint is defined in standard library or user's code? Both gcc and clang give consistent behavior.
The compiler knows no distinction between user code and the one in the standard library. Although the compiler can distinguish between standard library files and user code, I really do not see any reason to do so. All it sees is textual data that it can lex/parse/codegen.
I was studying C from K & R and got confused in part 4.4 of the book, when it is referring to scope rules. Before I go any further, let me just post the source file I am working on.
#include <stdio.h>
void first(void);
int main(void) {
printf("In main.\n");
first();
second();
return 0;
}
void first(void) {
printf("In first.\n");
}
void second(void) {
printf("In second.\n");
}
Now, unless I am more stupid than I imagine, the book gave me the idea that function prototypes (in the same file as the definition of the function) exist for scoping reasons. That is, they exist to allow the function to be declared at the top of a compiled file to for the rest of a source file to be notified for the existence of an "object" if I may so call it, ahead of time.
My issue with the above code is that in an Arch Linux Virtual Machine I am working on with GCC version 4.7.1 the above file can NOT compile and gives the following error: conflicting types for second.
However, when the very same code is run into my physical machine, sporting Ubuntu 12.04 with GCC version 4.6.3 it compiles just fine.
My question is: Is this a compiler feature? Because if it is not, I am surprised it compiles at all, seeing as there is no function prototype for second, main (if I have understood it correctly) should not be able to know about second's existence.
The "conflicting types" error message happens because most C compilers, upon encountering a function that has not been declared yet, will implicitly declare a prototype for that function returning an int. So when second() is encountered in main(), GCC 4.7.1 is inferring the following definition:
int second();
Then when the compiler reaches the function definition, notices that the inferred prototype's signature does not match the definition's signature, and aborts with an error.
As far as why 4.6.3 successfully compiles this code, the following is a guess. GCC 4.6.3 may have some bug (or feature, you decide) that allows function implementations to differ from their prototypes by their return type. Since C allows functions with non-void return types to terminate without returning anything (which makes their return value undefined), this could simply be a case of two sub-optimal things canceling each other out.
(The behavior in 4.6.3 could also be a change in default compiler options between versions, or perhaps you are invoking the compiler with different options.)
I'm looking at example abo3.c from Insecure Programming and I'm not grokking the casting in the example below. Could someone enlighten me?
int main(int argv,char **argc)
{
extern system,puts;
void (*fn)(char*)=(void(*)(char*))&system;
char buf[256];
fn=(void(*)(char*))&puts;
strcpy(buf,argc[1]);
fn(argc[2]);
exit(1);
}
So - what's with the casting for system and puts? They both return an int so why cast it to void?
I'd really appreciate an explanation of the whole program to put it in perspective.
[EDIT]
Thank you both for your input!
Jonathan Leffler, there is actually a reason for the code to be 'bad'. It's supposed to be exploitable, overflowing buffers and function pointers etc. mishou.org has a blog post on how to exploit the above code. A lot of it is still above my head.
bta, I gather from the above blog post that casting system would somehow prevent the linker from removing it.
One thing that is not immediately clear is that the system and puts addresses are both written to the same location, I think that might be what gera is talking about “so the linker doesn’t remove it”.
While we are on the subject of function pointers, I'd like to ask a follow-up question now that the syntax is clearer. I was looking at some more advanced examples using function pointers and stumbled upon this abomination, taken from a site hosting shellcode.
#include <stdio.h>
char shellcode[] = "some shellcode";
int main(void)
{
fprintf(stdout,"Length: %d\n",strlen(shellcode));
(*(void(*)()) shellcode)();
}
So the array is getting cast to a function returning void, referenced and called? That just looks nasty - so what's the purpose of the above code?
[/EDIT]
Original question
User bta has given a correct explanation of the cast - and commented on the infelicity of casting system.
I'm going to add:
The extern line is at best weird. It is erroneous under strict C99 because there is no type, which makes it invalid; under C89, the type will be assumed to be int. The line says 'there is an externally defined integer called system, and another called puts', which is not correct - there are a pair of functions with those names. The code may actually 'work' because the linker might associate the functions with the supposed integers. But it is not safe for a 64-bit machine where pointers are not the same size as int. Of course, the code should include the correct headers (<stdio.h> for puts() and <stdlib.h> for system() and exit(), and <string.h> for strcpy()).
The exit(1); is bad on two separate counts.
It indicates failure - unconditionally. You exit with 0 or EXIT_SUCCESS to indicate success.
In my view, it is better to use return at the end of main() than exit(). Not everyone necessarily agrees with me, but I do not like to see exit() as the last line of main(). About the only excuse for it is to avoid problems from other bad practices, such as functions registered with atexit() that depend on the continued existence of local variables defined in main().
/usr/bin/gcc -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -c nasty.c
nasty.c: In function ‘main’:
nasty.c:3: warning: type defaults to ‘int’ in declaration of ‘system’
nasty.c:3: warning: type defaults to ‘int’ in declaration of ‘puts’
nasty.c:3: warning: built-in function ‘puts’ declared as non-function
nasty.c:8: warning: implicit declaration of function ‘strcpy’
nasty.c:8: warning: incompatible implicit declaration of built-in function ‘strcpy’
nasty.c:10: warning: implicit declaration of function ‘exit’
nasty.c:10: warning: incompatible implicit declaration of built-in function ‘exit’
nasty.c: At top level:
nasty.c:1: warning: unused parameter ‘argv’
Not good code! I worry about a source of information that contains such code and doesn't explain all the awfulness (because the only excuse for showing such messy code is to dissect it and correct it).
There's another weirdness in the code:
int main(int argv,char **argc)
That is 'correct' (it will work) but 100% aconventional. The normal declaration is:
int main(int argc, char **argv)
The names are short for 'argument count' and 'argument vector', and using argc as the name for the vector (array) of strings is abnormal and downright confusing.
Having visited the site referenced, you can see that it is going through a set of graduated examples. I'm not sure whether the author simply has a blind spot on the argc/argv issue or is deliberately messing around ('abo1' suggests that he is playing, but it is not helpful in my view). The examples are supposed to feed your mind, but there isn't much explanation of what they do. I don't think I could recommend the site.
Extension question
What's the cast in this code doing?
#include <stdio.h>
char shellcode[] = "some shellcode";
int main(void)
{
fprintf(stdout,"Length: %d\n",strlen(shellcode));
(*(void(*)()) shellcode)();
}
This takes the address of the string 'shellcode' and treats it as a pointer to a function that takes an indeterminate set of arguments and returns no values and executes it with no arguments. The string contains the binary assembler code for some exploit - usually running the shell - and the objective of the intruder is to get a root-privileged program to execute their shellcode and give them a command prompt, with root privileges. From there, the system is theirs to own. For practicing, the first step is to get a non-root program to execute the shellcode, of course.
Reviewing the analysis
The analysis at Mishou's web site is not as authoritative as I'd like:
One, this code uses the extern keyword in the C language to make the system and puts functions available. What this does (I think) is basically references directly the location of a function defined in the (implied) header files…I get the impression that GDB is auto-magically including the header files stdlib.h for system and stdio.h for puts. One thing that is not immediately clear is that the system and puts addresses are both written to the same location, I think that might be what gera is talking about “so the linker doesn’t remove it”.
Dissecting the commentary:
The first sentence isn't very accurate; it tells the compiler that the symbols system and puts are defined (as integers) somewhere else. When the code is linked, the address of puts()-the-function is known; the code will treat it as an integer variable, but the address of the integer variable is, in fact, the address of the function - so the cast forces the compiler to treat it as a function pointer after all.
The second sentence is not fully accurate; the linker resolves the addresses of the external 'variables' via the function symbols system() and puts() in the C library.
GDB has nothing whatsoever to do the compilation or linking process.
The last sentence does not make any sense at all. The addresses only get written to the same location because you have an initialization and an assignment to the same variable.
This didn't motivate me to read the whole article, it must be said. Due diligence forces me onwards; the explanation afterwards is better, though still not as clear as I think it could be. But the operation of overflowing the buffer with an overlong but carefully crafted argument string is the core of the operation. The code mentions both puts() and system() so that when run in non-exploit mode, the puts() function is a known symbol (otherwise, you'd have to use dlopen() to find its address), and so that when run in exploit mode, the code has the symbol system() available for direct use. Unused external references are not made available in the executable - a good thing when you realize how many symbols there are in a typical system header compared with the number used by a program that includes the header.
There are some neat tricks shown - though the implementation of those tricks is not shown on the specific page; I assume (without having verified it) that the information for getenvaddr program is available.
The abo3.c code can be written as:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
void (*fn)(char*) = (void(*)(char*))system;
char buf[256];
fn = (void(*)(char*))puts;
strcpy(buf, argv[1]);
fn(argv[2]);
exit(1);
}
Now it compiles with only one warning with the fussy compilation options I originally used - and that's the accurate warning that 'argc' is not used. It is just as exploitable as the original; it is 'better' code though because it compiles cleanly. The indirections were unnecessary mystique, not a crucial part of making the code exploitable.
Both system and puts normally return int. The code is casting them to a pointer that returns void, presumably because they want to ignore whatever value is returned. This should be equivalent to using (void)fn(argc[2]); as the penultimate line if the cast didn't change the return type. Casting away the return type is sometimes done for callback functions, and this code snippet seems to be a simplistic example of a callback.
Why the cast for system if it is never used is beyond me. I'm assuming that there's more code that isn't shown here.
I am currently learning and experimenting with C and am using Bloodshed's DEV-C++ as an IDE.
Now, I just realized that the following piece of code (as it is...no includes or nothing) compiles and runs :
main ()
{
printf("%d", strlen("hello"));
}
Now, if I'm not mistaken, shouldn't two header files be included in this source for it to work ? stdio.h and string.h...but as you can see, I did not add them and the code still compiled and ran successfully.
My complaint is that I want the compiler to be "strict" because since I'm still learning C, I don't want the code to run if normally it shouldn't.
So, is there any way to prevent Dev-C++ from 'correcting my mistakes' when it comes to includes, ie making it more kinda "strict" ?
C90 had a feature (absent of C99 and C++) called implicit function declaration: when you used a name not declared yet in a function call, the compiler behaved as if
extern int identifier();
had been seen. That feature has been dropped from C99 and most compilers had option to warn about this even before C99 was promulgated.
Even when staying in C90, it is not recommended style to use this. If you have to maintain code making use of this and can't add prototypes, check that:
the functions returns an int (it is the case for printf but the validity is implementation dependent for strlen which returns a size_t which can be int or something else)
the function isn't variadic (it is the case for strlen but not printf)
the type of the arguments is not modified by default argument promotions (char, short, float are) and you must pay attention to cast pointers to void* when needed when the expected type is void*, you have to pay attention to cast NULL to the correct pointer type. (These are the same things you have to pay attention for variadic arguments BTW).
If those conditions aren't met -- and they aren't for any calls in your code -- you enter in the realm of undefined behavior.
I don't know if this actually is a DevC++ issue, but in any case you should consider ditching it. It is no longer being developed and is very buggy. I recommend changing to Code::Blocks, which is better in every way and alows you to use the very latest GCC compiler.
One of the possibilities for 'undefined behaviour' - which you get if you call a variadic function without a visible prototype - is that your code compiles and runs successfully.
If you're using gcc as the underlying compiler then you should be able to pass flags such as -std=c89 -pedantic -Wall -Wextra and get warnings about code such as the snippet that you've posted.