C++ printf: newline (\n) from commandline argument

15,030

Solution 1

No, do not do that! That is a very severe vulnerability. You should never accept format strings as input. If you would like to print a newline whenever you see a "\n", a better approach would be:

#include <iostream>
#include <cstdlib>

int main(int argc, char* argv[])
{
     if ( argc != 2 ){
         std::cerr << "Exactly one parameter required!" << std::endl;
         return 1;
     }

     int idx = 0;
     const char* str = argv[1];
     while ( str[idx] != '\0' ){
          if ( (str[idx]=='\\') && (str[idx+1]=='n') ){
                 std::cout << std::endl;
                 idx+=2;
          }else{
                 std::cout << str[idx];
                 idx++;
          }
     }
     return 0;
}

Or, if you are including the Boost C++ Libraries in your project, you can use the boost::replace_all function to replace instances of "\\n" with "\n", as suggested by Pukku.

Solution 2

At least if I understand correctly, you question is really about converting the "\n" escape sequence into a new-line character. That happens at compile time, so if (for example) you enter the "\n" on the command line, it gets printed out as "\n" instead of being converted to a new-line character.

I wrote some code years ago to convert escape sequences when you want it done. Please don't pass it as the first argument to printf though. If you want to print a string entered by the user, use fputs, or the "%s" conversion format:

int main(int argc, char **argv) { 
    if (argc > 1) 
        printf("%s", translate(argv[1]));
    return 0;
}

Solution 3

You can't do that because \n and the like are parsed by the C compiler. In the generated code, the actual numerical value is written.

What this means is that your input string will have to actually contain the character value 13 (or 10 or both) to be considered a new line because the C functions do not know how to handle these special characters since the C compiler does it for them.

Alternatively you can just replace every instance of \\n with \n in your string before sending it to printf.

Solution 4

passing user arguments directly to printf causes a exploit called "String format attack"

See Wikipedia and Much more details

Share:
15,030
Sebtm
Author by

Sebtm

Updated on June 04, 2022

Comments

  • Sebtm
    Sebtm almost 2 years

    How print format string passed as argument ?

    example.cpp:

    #include <iostream> 
    int main(int ac, char* av[]) 
    {
         printf(av[1],"anything");
         return 0;
    }
    

    try:

    example.exe "print this\non newline"
    

    output is:

    print this\non newline
    

    instead I want:

    print this
    on newline
    
  • C. K. Young
    C. K. Young about 14 years
    /me runs the program with a few copies of %n in the format string...mmmm.... :-P
  • Blindy
    Blindy about 14 years
    -1 Vulnerability aside, how is your "answer" answering the OP's question?
  • Mark Ransom
    Mark Ransom about 14 years
    Blanket statements are also dangerous. This would be perfectly fine in an environment where you have control over the parameters, via batch file for example.
  • C. K. Young
    C. K. Young about 14 years
    @PoweRoy: An untrusted format string can be used to corrupt memory in arbitrary ways. For example, with the %n format I mentioned, it writes out the number of currently-written characters into the address pointed to by the next argument. Since the attacker controls the whole format string (in this case), they also have control of what value gets written. Embed a few more %n and you get even more scribbling.
  • Michael Aaron Safyan
    Michael Aaron Safyan about 14 years
    @Mark, you might think you have control... but just wait until it ends up in a huge code base with other code from the organization. Do you have any idea how difficult it would be to track down and prevent it from ending up elsewhere? Better not to let that ever enter your codebase to begin with.
  • Runium
    Runium over 9 years