Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

passing format string to scanf as an command line argument vs hardcoding it

Tags:

c

scanf

I have following code:

#include <stdio.h>
int main()
{
    int i;
    char c;
    char *format_string = "%d\n";
    scanf(format_string, &i);
    printf("read: %d\n", i);

    printf("Let's check what is in the input buffer:\n");
    while (scanf("%c", &c) == 1)
    {
        printf("read from input buf: %d\n", c);
    }
}

If I run the code following way:

echo "5" | ./specific.out

The output is following:

read: 5
Let's check what is in the input buffer:

Here I have more general version of above code, where I pass format string from command line:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        exit(EXIT_SUCCESS);
    }

    int i;
    char c;

    char *format_string = argv[1];

    scanf(format_string, &i);
    printf("read: %d\n", i);

    printf("Let's check what is in the input buffer:\n");
    while (scanf("%c", &c) == 1)
    {
        printf("read from input buf: %d\n", c);
    }
}

If I run the code following way:

echo "5" | ./general.out '%d\n'

The output is following:

read: 5
Let's check what is in the input buffer:
read from input buf: 10

Why do I get different outputs?

like image 491
Wakan Tanka Avatar asked Dec 07 '25 06:12

Wakan Tanka


1 Answers

When you specify '%d\n' on the command line, you're not sending a % followed by d followed by a newline. You sending % followed by d followed by \ followed by n.

Because of this, the newline generated by the echo command doesn't match anything in the format string (specifically a newline doesn't match \), so it gets left in the input buffer.

To get the same result, your command line would have to look like this:

echo "5" | ./x1 '%d
'

On a side note, it's a bad idea for a format string to be under the control of a user, as that can lead to a format string vulnerability. Format strings are best left as string literals.

As an added bonus, if you use a string literal as a format string then your compile will also be able to generate warnings if the format string doesn't match the parameters passed to it.

like image 119
dbush Avatar answered Dec 09 '25 20:12

dbush