What does conversion specifier %n exactly do? [duplicate] - c

This question already has answers here:
What is the use of the %n format specifier in C?
(12 answers)
Closed 7 years ago.
I just encountered this by looking in the standard:
7.19.6.1 The fprintf function
in
8 The conversion specifiers and their meanings are:
regarding to:
n The argument shall be a pointer to signed integer into which is written the
number of characters written to the output stream so far by this call to
fprintf. No argument is converted, but one is consumed. If the conversion
specification includes any flags, a field width, or a precision, the behavior is
undefined.
What does this mean? What does %n do?
Did I get it correct, that acording to:
Returns
14 The fprintf function returns the number of characters transmitted
In this snippet:
int a, b;
b = printf ("Thi%n\s is just a test",&a);
a would equal to b?

the number of characters written to the output stream so far
"So far", means wherever you place your %n, the result will change. As of your example, it will be 3.
If your increase your %s position by one char, the resulting variable pointed will increase by one. Placing your %s at the very end of the string will make it equal to the value returned by printf

a = 3 and b = 19 for your case
a will be equal to number of character printed before %n.
Suppose you try to print printf ("This%sis%n just a test","coder", &a);
Then the value of a will be this + coder + is = 11.
And the value of b is always the total number of characters printed

Related

towlower() return "?" instead of this character in lower register

it is simple version just for ask, i have this program
wchar_t c;
wprintf(L"input\n");
wscanf(L"%d", &c);
wprintf(L"output\n");
wprintf(L"%lc", towlower(c));
and this input/output
if i input "W" there output "?", with another characters i have the same situation.
in the line wscanf(L"%d", &c);, you passed %d as format specifier. So wscanf() is searching for an integer, but you are passing a character instead. Changing to %c will solve it.
See the specification in the wscanf(3) manpage:
d Matches an optionally signed decimal integer, whose format is the same
as expected for the subject sequence of wcstol() with the value 10 for
the base argument. In the absence of a size modifier, the application
shall ensure that the corresponding argument is a pointer to int.
...
c Matches a sequence of wide characters of exactly the number specified
by the field width (1 if no field width is present in the conversion
specification).

Why does pushing space bar not put a value in array?

#include <stdio.h>
int main(){
printf("Enter 10 numbers: ");
int a[10], i = 0;
for (i = 0; i < 10; i++)
{
scanf("%d", &a[i]);
}
}
When I put value in each array, why pushing the space bar can put a value in the array?
For example when I write 1space2space3space then each value is put in each array (a[0], a[1], a[2]).
Why is this happening?
From the C Standard (7.21.6.2 The fscanf function)
12 The conversion specifiers and their meanings are:
d Matches an optionally signed decimal integer, whose format is the same as
expected for the subject sequence of the strtol function with the value 10
for the base argument. The corresponding argument shall be a pointer to
signed integer.
And (7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions)
...First, they decompose the input string into three parts: an initial, possibly empty, sequence of white-space characters (as
specified by the isspace function), a subject sequence resembling an
integer represented in some radix determined by the value of base, and
a final string of one or more unrecognized characters, including the
terminating null character of the input string. Then, they attempt to
convert the subject sequence to an integer, and return the result.
For such an input
1space2space3space
the first subject sequence is 1, the second subject sequence (after skipping white-space characters) is 2, and the third subject sequence is 3. They are used to store integers correspondingly in a[0], a[1], and a[2] because each subject sequence represents a valid integer.
Take into account that in general implementations use the so-called line buffering for text streams.
From the C Standard (7.21.3 Files)
... When a stream is line buffered, characters are intended to be
transmitted to or from the host environment as a block when a
new-line character is encountered.
As you are using scanf() with %d, the input stream is accepting integer values, and considering others as separator.

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

Does sscanf touch pointers if no match has been found? [duplicate]

This question already has answers here:
Is `sscanf` guaranteed not to change arguments that it doesn't find?
(5 answers)
Closed 8 years ago.
If a line does not match a [fsv]scanf format, does scanf guarantee not to touch the provided pointers that are not matched?
For example, if
int int1 = 3;
int int2 = 5;
sscanf(line, "%d %d", &int1, &int2);
returns 0, are the integers guaranteed to be still 3 and 5, or can int1 have been changed?
The short answer is yes, in your case you can guarantee that int1 and int2 have not changed.
However, I would advise against relying on this behaviour, as it's likely to produce code that is difficult to read - and because:
The long answer is it depends on your format string. Looking at the C11 standard for fscanf (s7.21.6.2.16), we have:
The fscanf function returns the value of the macro EOF if an input failure occurs
before the first conversion (if any) has completed. Otherwise, the function returns the
number of input items assigned, which can be fewer than provided for, or even zero, in
the event of an early matching failure.
Critically important is this definition of input items from later in 7.21.6.2:
An input item is defined as the longest sequence of input characters which does not exceed
any specified field width and which is, or is a prefix of, a matching input sequence
So. The number returned by scanf is the number of items read from the stream, not the number of pointers written to.
Additionally relevant is 7.21.6.2.2:
If the format is exhausted while arguments remain, the excess
arguments are evaluated (as always) but are otherwise ignored.
The behaviour of ignoring arguments that aren't written to is also made explicit in an example at the end of that section:
In:
#include <stdio.h>
/* ... */
int d1, d2, n1, n2, i;
i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
the value 123 is assigned to d1 and the value 3 to n1. Because %n can never get an input failure the value of 3 is also assigned to n2. The value of d2 is not affected. The value 1 is assigned to i.
In case you're not familiar with %n, it's "the number of characters read from the stream so far".
This is a great example to illustrate your question - here we have three pointers written to, and one pointer untouched. But, fscanf only returns 1 here - because it only assigned one "input item" from the stream.
So, in your example, yes, if you've got %d %d and you pass it something which causes 0 reads, then yes, the pointers will be untouched.
But, if you've got a %n in there, then your function could still return 0 or EOF while still consuming some input and writing to pointers. For example:
sscanf("aaa","aaa%n%d",&n1,&n2);
This writes 3 to n1, leaves n2 untouched, and returns EOF. And:
sscanf("aaa bbb","aaa%n%d",&n1,&n2);
This writes 3 to n1, leaves n2 untouched, and returns 0.
There should be at least as many of these arguments as the number of values stored by the format specifier of sscanf. Additional arguments are ignored by the function sscanf.
If line contains say "10 20", then int1 and int2 will be changed to 10 and 20 respectively.
However, if line contains say "aa bb", then int1 and int2 will be retained as 3 and 5 respectively.

understanding a notation in printf [duplicate]

This question already has answers here:
What does "%.*s" mean as a format specifier in printf?
(7 answers)
Closed 9 years ago.
This might be a very basic question to many of you, but I am not able to understand
what %.*s doing?
void substring(int i, int j, char *ch)
{
printf("The substring is: %.*s\n", j - i, &ch[i]);
//what is %.*s doing?
}
The * is taking the length limit for the string from the argument before the string. So the printf will output (at most) j - i characters from &ch[i] to stdout. If the string is shorter, then the entire string will be printed, but it will not be blank padded.
Here is a good reference for printf: http://en.cppreference.com/w/c/io/fprintf.*
And this is what it says:
. followed by integer number or * that specifies precision of the conversion. In the case when * is used, the precision is specified by an additional argument of type int. If the value of this argument is negative, it is ignored. See the table below for exact effects of precision.
And for s, it says:
Precision specifies the maximum number of bytes to be written.
So in your case, it prints a maximum of j-i characters.
* In fact, it's a very good reference for just about all standard C and C++ libraries. Use it!

Resources