sscanf function changes the content of another string

前端 未结 1 1991
谎友^
谎友^ 2021-01-24 20:50

I am having problems reading strings with sscanf. I have dumbed down the code to focus on the problem. Below is a function in the whole code that is supposed to ope

相关标签:
1条回答
  • 2021-01-24 21:28

    The string begin isn't big enough to hold the four characters that sscanf will read and its \0 terminator. If the \0 is written into atm (depending on where the strings are in memory), atm would be modified. From the sscanf manpage, about the s directive:

    s    Matches a sequence of non-white-space characters; the next pointer must be a pointer to character array that is long enough to hold the input sequence and the terminating null byte ('\0'), which is added automatically. The input string stops at white space or at the maximum field width, whichever occurs first.

    I was able to reproduce this behavior on my machine, though the exact positioning of the strings in memory was a bit different. By printing the addresses of the strings, though, it is easy to figure exactly what's happening. Here's a minimal example:

    #include<stdio.h>
    
    int main() { 
      char begin[2];
      char atm[100]="ATOM";
    
      printf("begin:    %p\n", begin);
      printf("begin+16: %p\n", begin+16);
      printf("atom:     %p\n", atm);
      printf("1 %s\n",atm);
      sscanf("AAAABBBBCCCCDDDD", "%16s", begin);
      printf("2 %s \n",atm);
      return 0;
    }
    

    This produces the output:

    $ ./a.out 
    begin:    0x7fffffffe120
    begin+16: 0x7fffffffe130
    atom:     0x7fffffffe130
    1 ATOM
    2  
    

    I printed the values of the pointers to figure out how big a string it would take to overflow into atm. Since (on my machine) atom begins at begin+16, reading sixteen characters into begin puts a null terminator at begin+16, which is the first character of atm, so now atm has length 0.

    0 讨论(0)
提交回复
热议问题