When printing string why I am getting warning when constant qualifier not used in c?

82 views Asked by At
#include<stdio.h>
int main()
{
  const char arr[10] = "hello";
  printf(arr);
  return 0;
}

When compiling the above code with don't gave any warning. But when I remove the
const from const char arr[10] it gives a warning:

<source>: In function 'main':
<source>:5:10: warning: format not a string literal and no format arguments [-Wformat-security]
    5 |   printf(arr);
      | 

Why I am getting like this? How the const keyword make difference? Here I am compiling with gcc -Wformat -Wformat-security ….

2

There are 2 answers

4
John Bollinger On BEST ANSWER

But when I remove the const from const char arr[10] it gives warning like format not a string literal and no format argument. Why I am getting like this?

printf() requires you to provide a format string, and allows you to provide additional arguments as needed to match whatever conversion specifiers appear in the format.

It is risky, in general, to use a modifiable string as a printf format, because it may turn out to have unexpected conversion specifiers in it. This is primarily an issue with data read at runtime, and your particular string would be ok, but GCC's warning doesn't look so deeply. It just sees a modifiable string as a format and issues the warning.

Safer alternatives that will not draw a warning from gcc would include using fputs():

    fputs(arr, stdout);

... and using printf() with an appropriate format:

  printf("%s", arr);

.

How the const keyword make difference?

Apparently GCC does not distinguish between an array of const char and a string literal for this purpose. That's not unreasonable, but it does make the diagnostic a little confusing.

3
dbush On

While it's valid to pass a char * (which a char array decays to) to a function expecting a const char *, it's bad practice to pass something that's not a string constant as the first argument to printf, which is what the warning is about.

This argument is a format string that dictates how any additional arguments are processed. If this first argument is not a string constant but something that the user can control, it opens up the possibility of passing in format specifiers that would process more arguments than were passed. This can allow for reading memory that wasn't intended to be read or writing memory not intended to be written and is considered a security hole.