Undefined behaviour of the compiler - c

Hey what will be the the output of the following code, it is not working as it should.
int j=65;
printf("j>=65?%d:%c",j);
In this case it should print: j>=65, and then match the next %d with the j so print 65, and then %c is printing l how the l is printed.

Instead of
Printf("j>=65?%d:%c",j);
there has to be at least
printf("j>=65?%d:%c",j);
The code has undefined behaviour because the number of format specifiers is greater than the number of following arguments.
I think you mean the following
printf( j >= 65 ? "%d" : "%c", j );
in this case there will be outputed 65.

The format specifier "j>=65?%d:%c" has two %... pieces, they indicate that two values are to be printed. The format is used within printf("j>=65?%d:%c",j); which only provides one value to be printed.
There is no checking in C that the printf is given the correct number of arguments for the format, there is no protection at run time for what actually happens when too few arguments are given. That is undefined behaviour. The C language allows the programmer to write many things that lead to undefined behaviour.

You should not use conditional operation inside double quotes like this printf("j>=65?%d:%c",j);. you are having two format specifier and only one argument. so it results in undefined behavior. so j>=65? is printed first, %d prints 65, %c expects arguments, but there is no arguments, so it prints anything. Results in undefined behavior. You should use No of arguments equal to the no of format specifiers.
When i run your code in my system i got-
root#ubuntu:~/c/basics# cc con1.c
con1.c: In function ‘main’:
con1.c:6:1: warning: format ‘%c’ expects a matching ‘int’ argument [-Wformat=] // see this warning
printf("j>=65?%d:%c",j);
^
root#ubuntu:~/c/basics# ./a.out
j>=65?65:� // see this undefined symbol
Try the following change and fix it-
printf(j>=65 ? "%d" : "%c",j);
when the condition is true it prints 65 and when condition fails it prints the character(For that input value)
or
j>=65 ? printf("%d",j) : printf("%c",j);

You call printf() with two format specifiers, but pass only one parameter after the format string. The function doesn't know how many parameters you pass, so it assumes you did pass two arguments. The result is, it reads the random garbage that just happens to be at the memory location where would be the second parameter if you did pass it. Run it another day, compile it with different compiler or different options, and you get different result (in worst case, segmentation fault).

Related

Why is printf() printing out in this code?

This simple code is puzzling me - I am deliberately printing out more integers than I passed to printf. I expected an error. I got weird numbers - where are they coming from?
#include <stdio.h>
/* learn arrays */
void main(){
int pout;
pout = 6;
printf("%i %i %i\n%i %i %i\n%i %i %i\n", pout);
}
One example of the output:
6 608728840 0
-885621664 -885543392 608728816
0 0 -889304251
The single digits do not change with repeated runs, but the large integers do.
It's one of printf string format vulnerability. You are trying to call more argument than there actually are, so printf takes whatever he can on the stack.
It was (and still is) very used to exploit programs into exploring stacks to access hidden information or bypass authentication for example.
Viewing the stack
printf ("%08x %08x %08x %08x %08x\n");
This
instructs the printf-function to retrieve five parameters from the
stack and display them as 8-digit padded hexadecimal numbers. So a
possible output may look like:
40012980 080628c4 bffff7a4 00000005 08059c04
See this for a more complete explanation.
Because it's undefined behavior. If the number of specifiers is larger than the number of matching parameters or their types are incompatible, the behavior is undefined.
This qoute is from the c11 standard draft
7.21.6.1 The fprintf function
The fprintf function writes output to the stream pointed to by stream, under control of the string pointed to by format that specifies how subsequent arguments are converted for output. If there are insufficient arguments for the format, the behavior is undefined. If the format is exhausted while arguments remain, the excess arguments are evaluated (as always) but are otherwise ignored. The fprintf function returns when the end of the format string is encountered.
If a conversion specification is invalid, the behavior is undefined.282) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
I highlighted the relevant parts making them bold.
The int reserves some RAM but you didn't wrote anything in so it shows you what numbers are random somewhere in your RAM

why does printf() gives random output when it should be 0?

so as printf() is a function and it returns the number of characters written if successful or negative value if an error occurred, looking at this example, the output as expected is zero.
#include <stdio.h>
int main(void)
{
printf("%d");
return 0;
}
now when I add some more of these %d : http://ideone.com/brw5vG
the output changes to this:
0 134513819 -1216430092 134513808
I am not able to figure out whats up with the random garbage values? There is a negative value here in the output as well, and a negative value justifies an error, so can anyone pinpoint what is the error here exactly?
Please be concise and specific. Thanks.
Because "%d" means an integer is expected. You don't pass any, so you get undefined behaviour.
Note that g++ 4.8.2 gives a useful warning:
warning: format '%d' expects a matching 'int' argument [-Wformat=]
similarly for clang++ 3.4:
warning: more '%' conversions than data arguments [-Wformat]
the output as expected is zero
printf("%d");
You should not expect anything as your program invokes undefined behavior.
(C99, 7.19.6.1p2) "[...] If there are insufficient arguments for the format, the behavior is
undefined.[...]"
You are mis-specifiying the format string to printf this is undefined behavior and you should have no expectations as to the result. By specifying %d you are telling printf to expect an int argument which you have not provided.
If we look at the C99 draft standard section 7.19.6.1 The fprintf function which also covers pritnf with respect to format specifiers says:
[...]If there are insufficient arguments for the format, the behavior is undefined.[...]
The problem is in how you pose the question; you assume it "should be 0." The fact is that this is undefined behavior, and printf will substitute for %d whatever happens to be in the stack.
Your code invokes undefined behavior. Anything could be happen.
The C11 Standard says in section 7.21.6 Formatted input/output functions:
If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
You are passing no argument for the corresponding %d specifier.
There are 2 issues at hand: First is why doesn't the compiler issue an error about this bad call to printf(), and second is why you get garbage output. I'll answer them one at a time.
printf() is a tricky function. While most functions have a constant amount of arguments passed to them, printf() is different.
For example, if we take this simple function:
int max(int a, int b) {
if (a > b) return a;
else return b;
}
You can see that this function always receives 2 arguments. This is also something that the compiler knows, and enforces when you compile you code. This is why a call such as max(4) won't work. The compiler will see that we are passing max() 1 argument instead of 2 and it will issue an error.
printf() is a function that takes a variable amount of arguments, and this amount is determined by the amount of format specifiers (things that start with %) in the format string. This means that the compiler cannot know at compile time if the amount of arguments that you passed to printf is enough (or maybe too much).
The reason that you get garbage printed is because of how functions read their input arguments. All input arguments for a function reside on the stack. These are pushed into the stack before the function is called and later addressed by the function. In this case, printf() expects to have an extra argument besides the format string (because of the %d), and so it looks in the address where its 2nd argument might have been. Alas, that argument wasn't passed, so it will actually look into a place in the stack that might contain anything else (a return address, a frame pointer, a local variable of an enclosing scope or other).
You can read more about how function calls work here.

What is the difference between %d and %*d in c language?

What is %*d ? I know that %d is used for integers, so I think %*d also must related to integer only? What is the purpose of it? What does it do?
int a=10,b=20;
printf("\n%d%d",a,b);
printf("\n%*d%*d",a,b);
Result is
10 20
1775 1775
The %*d in a printf allows you to use a variable to control the field width, along the lines of:
int wid = 4;
printf ("%*d\n", wid, 42);
which will give you:
..42
(with each of those . characters being a space). The * consumes one argument wid and the d consumes the 42.
The form you have, like:
printf ("%*d %*d\n", a, b);
is undefined behaviour as per the standard, since you should be providing four arguments after the format string, not two (and good compilers like gcc will tell you about this if you bump up the warning level). From C11 7.20.6 Formatted input/output functions:
If there are insufficient arguments for the format, the behavior is undefined.
It should be something like:
printf ("%*d %*d\n", 4, a, 4, b);
And the reason you're getting the weird output is due to that undefined behaviour. This excellent answer shows you the sort of things that can go wrong (and why) when you don't follow the rules, especially pertaining to this situation.
Now I wouldn't expect this to be a misalignment issue since you're using int for all data types but, as with all undefined behaviour, anything can happen.
When used with scanf() functions, it means that an integer is parsed, but the result is not stored anywhere.
When used with printf() functions, it means the width argument is specified by the next format argument.
The * is used as an indication that the width is passed as a parameter of printf
in "%*d", the first argument is defined as the total width of the output, the second argument is taken as normal integer.
for the below program
int x=6,p=10;
printf("%*d",x,p);
output: " 10"
the first argument ta passed for *, that defines the total width of the output... in this case, width is passed as 6. so the length of the entire output will be 5.
now to the number 10, two places are required (1 and 0, total 2). so remaining 5-2=3 empty string or '\0' or NULL character will be concatenated before the actual output

What does %0x%x mean in C/C++ programming?

I have the following code, but I'm not sure what %0x%x means in the following code?
sprintf(buf, "pixel : %0x%x \n", gpbImageData[100]);
OutputDebugString(buf);
gpbImageData[100] is pointing to an image data in the memory.
Your example causes undefined behaviour. The format string will cause sprint to expect two int values:
%0x
%x
Both of these mean exactly the same thing - print a value as a hexadecimal number. However, the call you've shown passes only one argument.
Are you sure it doesn't say 0x%x? If it doesn't, it's probably supposed to... that would be more normal, and will print the passed-in value as a hexadecimal number prefixed with 0x.
Your code as shown should cause a warning. clang gives:
example.c:5:15: warning: more '%' conversions than data arguments [-Wformat]
printf("%0x%x\n", 125987);
~^
1 warning generated.
and gcc says:
example.c: In function ‘main’:
example.c:5: warning: too few arguments for format
example.c:5: warning: too few arguments for format
Both without providing any flags at all.
You certainly meant this format string "0x%x"
sprintf(buf, "pixel : 0x%x \n", gpbImageData[100]);
This adds the 0x prefix to the hexadecimal numbers when they are written in buf.
Note that you can achieve the same thing with the flag character #:
sprintf(buf, "pixel : %#x \n", gpbImageData[100]);
The correct format is "0x%x" as ouah and Carl Norum said. Whatever gpbImageData[100] content (pointer or number), %x will print its value as a hexadecimal number. 0x is just a text. Maybe "gpbImageData" is an array of pointers.

Please explain this ambiguity in C

When I am compiling this program I am getting some random number as output.. In Cygwin the output is 47 but in RHEL5, it is giving some negative random numbers as output.
Can anyone tell me the reason?
Code:
main()
{
printf("%d");
}
This program provokes undefined behavior since it does not follow the rules of C. You should give printf one argument per format specifier after the format string.
On common C implementations, it prints whatever happens to be on the stack after the pointer to "%d", interpreted as an integer. On others, it may send demons flying out of your nose.
It is Undefined Behaviour.
On 3 counts:
absence of prototype for a function taking a variable number of arguments
lying to printf by telling it you are sending 1 argument and sending none
absence to return a value from main (in C99 a return 0; is assumed, but your code definitely isn't C99)
Anything can happen.
printf expects a second argument, so it reads whatever happens to be on the stack at that location. Essentially it's reading random memory and printing it out.

Resources