By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,952 Members | 909 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,952 IT Pros & Developers. It's quick & easy.

Examples of UB with incorrect specifier in printf()

P: 3
C99 says:

"If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined."

I know what UB is. However, I am interested in a particular example of how can UB look like in such situation. For example, on x86 it may fail:
Expand|Select|Wrap|Line Numbers
  1.     int i = 10;
  2.     printf("%s\n", i);
Another example of UB I can think of is when i would be a trap value for a given type but there is no trap value in x86. What are other examples of UB either on x86 or other achitectures in this case?
Oct 27 '15 #1
Share this Question
Share on Google+
3 Replies


weaknessforcats
Expert Mod 5K+
P: 9,197
Just have one typecast in your program and you have UB.
Oct 27 '15 #2

P: 3
wtf? Is this illegal too:

size_t s = 1;
printf("%llu\n", (unsigned long long) s);
Oct 27 '15 #3

weaknessforcats
Expert Mod 5K+
P: 9,197
On my machine:

Expand|Select|Wrap|Line Numbers
  1. size_t s = 1;
  2.     printf("%llu\n",  s);
  3.     printf("%llu\n", (unsigned long long) s);
the execution result is:

Expand|Select|Wrap|Line Numbers
  1. 658839178552344321
  2. 1
  3.  
That is UB. Unless you step in and force s to be an unsigned long long, this printf function croaks. printf ASSUMES %llu is safe to display the argument as an unsigned long long. Apparently, unless you jump in and tell the compiler to use it as an unsigned long long, you get a bad result from printf.

The typecast has broken type safety. The display is a unsigned long long but the program is using another variable of type size_t.

Now I realize that weaknesses in C force you to cast all the time. Check this out:

Expand|Select|Wrap|Line Numbers
  1. const int var = 10;
  2. int* ptr = &(int)var;
  3.     *ptr = 25;
  4.     printf("%d\n %d\n", var, *ptr);
  5.  
On my machine I get
Expand|Select|Wrap|Line Numbers
  1. 25
  2. 25
I was able to change a const int from 10 to 25 by typecasting the address of a const int to be the address of an int. Then by using a pointer to int, the value of the const was changed.

So the program is using a const of 10 for whatever until the typecast when it now starts using 25. You have no idea when you make a function call using this varable whether it is a const 10 or a const 25.

C++ won't even compile this code.
Oct 27 '15 #4

Post your reply

Sign in to post your reply or Sign up for a free account.