Overflow on scanf ("% 8s" string)?

I know that you can overflow regular code:

char string [9];

scanf ("% s" string).

But is scanf overflow possible ("% 8s" string)? 8 is just an example.

I know that "% 8s" works as a delimiter, but I also notice that when you enter a string longer than 8 characters, the program will end because:

stack detection detected * : ./ a.out terminated

======= Backtrace: ===========

...

Obviously, a flag that detects stack breaks is enabled by GCC by default. Since this is a stack break, I assume that it is still possible to overflow and execute arbitrary code.

Unlike the usual overflow, which controls the caller scanf ("% s"), if scanf ("% 8s") can overflow, it will overflow in the scanf function, so that when scanf tries to return, control will be gained.

But scanf is syscall, which requires a switch mode (switching from user mode to kernel mode), and internally it will cause things like reading in stdin, etc. Therefore, I’m not sure if we can overflow in kernel mode or something like that.

Comments are welcome!

UPDATE →

char string [9] is assumed in the above example. char string [8] in the following valid code.

The question is really about the seemingly contradictory story between safe scanf ("% 8s") and GCC abortion due to a stack crash.

Simplified code:

void foo(pass some pointer) { char input[8]; int input_number = 0; while (1) { // looping console printf some info; scanf("%8s", input); input_number = atoi(input); if ((strlen(input) == 1) && (strncmp(input, "q", 1) == 0)) { input_number = -1; } switch (input_number) { case -1: to quit the console if input = 'q'; default: to print info that pointer refers to; ... } } } 

Note:

  • foo is being called by someone else.
  • Although the string has a value of 8 bytes in real-time code with "% 8s", I do not think that this leads to a rout.
+4
source share
4 answers

See http://www.opengroup.org/onlinepubs/009695399/functions/scanf.html :

Each directive consists of one of the following ... An optional non-zero decimal integer defining the maximum field width.

s
Matches a sequence of bytes that are not space characters. The application must ensure that the corresponding argument is a pointer to the start byte of an array of char, signed char or unsigned char large enough to accept a sequence and terminating null character code that should be added automatically.

Thus, it will not overflow the 9-byte string buffer.

+8
source

Never use scanf (or fscanf ) if you want your input to be reliable.

You should use fgets (or similarly the "buffer overflow protected" option), then use sscanf .

The main problem with scanf and fscanf is that your file pointer may be in an undefined position if the line does not match the expected format (i.e. if scanf fails). Using the fgets/sscanf method makes it much easier to ensure that you are on the line boundary without having to use ftell and fseek to move around the file.

As for your specific request for buffer overflows, in the C standard it can be said:

... the corresponding argument must be a pointer to the source element of the character array, large enough to accept a sequence and a terminating null character to be added automatically.

So, for the format "%8s" you need a 9-character array.

I suspect you have another problem in your code. Using a test program:

 #include <stdio.h> int main(int argc, char* argv[]) { char x1; char a[9]; char x2; x1 = x2 = ' '; scanf ("%s",a); printf ("[%c] [%s] [%c]\n",x1,a,x2); return 0; } 

I get:

 pax> ./qq.exe dfjdhadgha...lghjdfgjhd [s] [dfjdhadgha...lghjdfgjhd] [ ] 6 [main] qq 4744 _cygtls::handle_exceptions: Error while dumping state (probably corrupted stack) Segmentation fault (core dumped) 

When I change the same program to use "%8s" , I get (for exactly the same input):

 pax> ./qq.exe dfjdhadgha...lghjdfgjhd [ ] [dfjdhadg] [ ] 
+3
source

if a line is allocated for less than 8 charters, it will certainly overwrite the buffer, and scanf will not add a null terminator. But as long as you have enough space in the line for your value, you should not correspond.

+1
source

As ysth pointed out, an array should be able to contain a string and a terminating null character, so using an 8-byte array (especially if it is allocated on the stack, as in your code), it is very likely to mess it up.

+1
source

All Articles