Like Tree1Likes
  • 1 Post By Feversaint

fscanf - major crash (STATUS_ACCESS_VIOLATION)

This is a discussion on fscanf - major crash (STATUS_ACCESS_VIOLATION) within the C Programming forums, part of the General Programming Boards category; I'm slightly (see: very) confused with this issue because I've been using this function just fine for over a month ...

  1. #1
    Registered User
    Join Date
    Sep 2011
    Posts
    15

    fscanf - major crash (STATUS_ACCESS_VIOLATION)

    I'm slightly (see: very) confused with this issue because I've been using this function just fine for over a month and now my program is screeching to a halt at a certain point in it.

    Right now it will read the three instances of "NEW_MON_SPAWNER" below as it should. Then on it's fourth attempt to find the "NEW_MON_SPAWNER" token, it will give the below error at the line indicated below. I'm assuming this has something to do with the EOF, but I'm not really sure. One thing I'm curious about is if fscanf returns EOF at one point, then I go and fscanf again, will it return EOF again - or will it just explode? I've been using it in a manner like that for a while and it's just now dieing on me now that I added things elsewhere.

    Also, recently I learned the trick of looking in the stackdump and looking up the given functions using "info symbol" in gdb, but sadly this stack dump only gives a cygwin function (or at least I think it is- either way gdb itself cant identify it). I'll provide it anyway just incase it helps.

    If you need any more information than what I've provided to help, just let me know and I'll be happy to provide it.

    Thanks for your time in advance!

    [EDIT] Forgot to mention - I only found the line it was crashing on by stepping through it in gdb.


    The error...
    Code:
          2 [main] ? 2880 exception::handle: Exception: STATUS_ACCESS_VIOLATION
       1962 [main] ? 2880 open_stackdumpfile: Dumping stack trace to main.exe.stackdump
    main.exe.stackdump
    Code:
    Exception: STATUS_ACCESS_VIOLATION at eip=610C3576
    eax=00000000 ebx=00290000 ecx=00000000 edx=00C38020 esi=0028CD49 edi=00000000
    ebp=0027F338 esp=0027F178 program=C:\cygwin\home\Feversaint\C\team_ep\trunk\main.exe, pid 2880, thread main
    cs=0023 ds=002B es=002B fs=0053 gs=002B ss=002B
    Stack trace:
    Frame     Function  Args
    0027F338  610C3576  (00000000, 00000000, 00000000, 00000000)
    End of stack trace
    "custio.c"
    Code:
    /*-----------------------------------------------------------------
    Searches for a token within a file and stops on the line
      after the token, or EOF - which ever comes first.
    ------------------------------------------------------------------*/
    bool AdvanceFilePastToken(FILE* file, const char* token, char delim)
    {
      bool success;
      char buffer[FILE_BUFFER_SIZE]; /* currently 400 */
      
      success = false;
      
      while (fscanf(file, "%s" , buffer) != EOF)
      {
        /* Removes all commas (in this case) from the read string */
        ExtractDelimString(buffer, delim); 
        
        if (strcmp(buffer, token) == 0) /* <-- Segfault here */
        {
          success = true;
          break;
        }
      }
      
      return success;
    }
    "level1.lvl.csv" (file being read when segfault occurs)
    Code:
    ########################################LEVEL,
    LEVEL_NAME,
    null,
    ,
    ARTBANK_FILE_NAME,
    assets/level/level1.ab.csv,
    ,
    WAYPOINT_FILE_NAME,
    assets/level/level1.wp.csv,
    ,
    ________________________________WORLDGEOMETRY,
    ,
    ////////////////////////////////////////GEOMETRY,
    NEW_WORLD_GEOMETRY,
    ,
    NAME,
    assets/objectdata/testmap.go.csv,
    ,
    POSITION,
    0,0
    ,
    ANIMATED,
    0,
    ,
    ________________________________WAVES,
    ,
    ********************************SPAWN,
    NEW_MON_SPAWNER,
    ,
    NAME,
    spawn1,
    ,
    WAVE_NUM,
    1,
    ,
    POSITION,
    40,10
    ,
    MASTER,
    assets/objectdata/test_ent_green.go.csv,
    ,
    TOTAL_SPAWNS,
    5,
    ,
    SPAWN_START_TIME,
    0,
    ,
    SPAWN_INTERVAL,
    1,
    ,
    ********************************SPAWN,
    NEW_MON_SPAWNER,
    ,
    NAME,
    spawn2,
    ,
    WAVE_NUM,
    1,
    ,
    POSITION,
    20,10
    ,
    MASTER,
    assets/objectdata/test_ent_yellow.go.csv,
    ,
    TOTAL_SPAWNS,
    20,
    ,
    SPAWN_START_TIME,
    2.5,
    ,
    SPAWN_INTERVAL,
    0.25,
    ,
    ********************************SPAWN,
    NEW_MON_SPAWNER,
    ,
    NAME,
    spawn3,
    ,
    WAVE_NUM,
    1,
    ,
    POSITION,
    60,10
    ,
    MASTER,
    assets/objectdata/test_ent_white.go.csv,
    ,
    TOTAL_SPAWNS,
    4,
    ,
    SPAWN_START_TIME,
    4,
    ,
    SPAWN_INTERVAL,
    1,
    Last edited by Feversaint; 10-29-2011 at 03:35 AM.

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,755
    > One thing I'm curious about is if fscanf returns EOF at one point, then I go and fscanf again, will it return EOF again - or will it just explode?
    Well in the absence of doing anything else, it will just keep returning EOF.

    The other things you could do in the mean time would be things like rewind() or fsee() + clearerr().

    In gdb, you could try
    print token
    when it has segfaulted, but from here it looks like for all the world that it is a NULL pointer (given the number of registers which are currently zero).

    There doesn't seem to be any single word in your text file which would overflow buffer.

    Or is your text file actually just one single line just over 1000 characters long, completely devoid of any spaces or newlines.
    In which case, you have a massive buffer overrun.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Registered User
    Join Date
    Aug 2010
    Posts
    231
    Quote Originally Posted by Feversaint View Post
    Code:
      while (fscanf(file, "%s" , buffer) != EOF)
      {
    Its a newbie mistake, because its a potentially-infinite loop if fscanf returns 0.
    Its also UB, if your file contains a 'word' with >= 400 chars.

  4. #4
    Registered User
    Join Date
    Sep 2011
    Posts
    15
    As to the buffer - the file does contain newlines at the end of every line. The buffer is set to 400 because there's another file that contains the contents of a 2D array which represents the game world (which is under 400 characters - but close). I will look into the things Salem suggested. Thanks both of you for your input .

  5. #5
    Registered User
    Join Date
    Sep 2011
    Posts
    15
    Wow I am stupid :/ I pointed my comment at the wrong line. It's actually a different line that causes the crash - indicated below. I guess that's what I get for banging my head against my computer for 4 hours and posting at one in the morning. My apologies.

    Code:
    /*-----------------------------------------------------------------
    Searches for a token within a file and stops on the line
      after the token, or EOF - which ever comes first.
    ------------------------------------------------------------------*/
    bool AdvanceFilePastToken(FILE* file, const char* token, char delim)
    {
      bool success;
      char buffer[FILE_BUFFER_SIZE]; /* currently 400 */
      
      success = false;
      
      while (fscanf(file, "%s" , buffer) != EOF)  /* <--where It actually crashes */
      {
        /* Removes all commas (in this case) from the read string */
        ExtractDelimString(buffer, delim); 
        
        if (strcmp(buffer, token) == 0) /* <--where I said it crashes */
        {
          success = true;
          break;
        }
      }
      
      return success;
    }

  6. #6
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,755
    The most likely scenario in that case is you failed to open the file, didn't check that file was NULL and proceeded to try and read from the file.

    Or do you have something like this to open the file?
    if ( file = fopen("level1.lvl.csv", "r") == NULL )
    Note: this is wrong, the precedence is all screwed up.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  7. #7
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,263
    Quote Originally Posted by Feversaint View Post
    Code:
      char buffer[FILE_BUFFER_SIZE]; /* currently 400 */
    
      ...
      while (fscanf(file, "%s" , buffer) != EOF)  /* <--where It actually crashes */
    That's a pretty sweet buffer overflow you got there. It'd be a shame if anyone were to... exploit it.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  8. #8
    Registered User
    Join Date
    Sep 2011
    Posts
    15
    If you want me to post the whole function that this is from just let me know, I just tried to trim out what I though was unnecessary info.

    Code:
       FILE *waveFile;
        
        level->monSpawners = New_LL_MONSPAWN();
       
        waveFile = fopen(waveFileName, "r"); /* OPEN */
        if (waveFile != NULL) /* NULL check */
        {   
        /* The crash takes place in this func */
          while (AdvanceFilePastToken(waveFile, "NEW_MON_SPAWNER", fileDelim)) 
          {
            /* Load a new monster spawner and add it to a linked list */
            /* The file is read multiple times here but is not opened or closed */ 
          }
          
          fclose(waveFile); /* CLOSED */
        }
    As for
    That's a pretty sweet buffer overflow you got there. It'd be a shame if anyone were to... exploit it.
    Could you elaborate a little on that please? I think I understand what buffer overflow is, but how would this be vulnerable to it (I'm relatively new to c). From looking at it I'd guess you're saying that if someone were to provide a file that has over 400 chars on a line, it would overflow? Or is there something more to it?

  9. #9
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,755
    Do you call malloc / calloc / realloc / free anywhere in your code?

    If you put this in your main(), and ONLY this, does it work?
    Code:
        waveFile = fopen(waveFileName, "r"); /* OPEN */
        if (waveFile != NULL) /* NULL check */
        {   
        /* The crash takes place in this func */
          while (AdvanceFilePastToken(waveFile, "NEW_MON_SPAWNER", fileDelim)) 
          {
            /* Load a new monster spawner and add it to a linked list */
            /* The file is read multiple times here but is not opened or closed */ 
          }
          
          fclose(waveFile); /* CLOSED */
        }
    Basically, the code where it is crashing might be perfectly OK. If some damage was done earlier on, then where you're seeing the crash could just be an innocent victim.
    Prove this is the case by running the suspect code in isolation.

    TBH, you would be better served by downloading https://www.virtualbox.org/ and installing a REAL Linux OS inside it, instead of using cygwin.
    For one thing, you get to use some rather nifty tools like valgrind to help you locate memory abuse issues.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  10. #10
    Registered User
    Join Date
    Sep 2011
    Posts
    15
    I'll try and isolate it like that (working on that as we speak).

    Unfortunately I'm stuck with cygwin because this is for a school project and the only way we can get different colors is using the cygwin VT features that allow use of ansi escape sequences. Next semester we can use windows.h (thank god for that).

    One last question for now - just to be sure: Is it okay to have the same file open in two different places at once? Like say I have a function that receives a filename, then opens a file based on that, then passes the same filename into another function which creates a new FILE * and opens using the same file name. So long as they're both read only - this should be fine, right? I've been doing it for a while, but I want to be sure it wasn't just working by chance and is now screwing me over.

    Thanks again for all the help & advice!

  11. #11
    Registered User
    Join Date
    Aug 2008
    Location
    Belgrade, Serbia
    Posts
    163
    Quote Originally Posted by Feversaint View Post
    One last question for now - just to be sure: Is it okay to have the same file open in two different places at once? Like say I have a function that receives a filename, then opens a file based on that, then passes the same filename into another function which creates a new FILE * and opens using the same file name. So long as they're both read only - this should be fine, right? I've been doing it for a while, but I want to be sure it wasn't just working by chance and is now screwing me over.
    If the application is single-threaded, I suppose there shouldn't be any problems.
    Vanity of vanities, saith the Preacher, vanity of vanities; all is vanity.
    What profit hath a man of all his labour which he taketh under the sun?
    All the rivers run into the sea; yet the sea is not full; unto the place from whence the rivers come, thither they return again.
    For in much wisdom is much grief: and he that increaseth knowledge increaseth sorrow.

  12. #12
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Feversaint View Post
    One last question for now - just to be sure: Is it okay to have the same file open in two different places at once? Like say I have a function that receives a filename, then opens a file based on that, then passes the same filename into another function which creates a new FILE * and opens using the same file name. So long as they're both read only - this should be fine, right? I've been doing it for a while, but I want to be sure it wasn't just working by chance and is now screwing me over.
    IF both files are only being read, this should be no problem...

    However... if either of the two places (or threads) writes to the file, it should use whatever form of file locking is appropriate to the OS you're working under... That is... lock the file...write to the file... unlock it. This is to prevent simultaneously reading the portion of the file that is being written. (Not all C implementations provide this, so you may need to use your OS API's file management.)

  13. #13
    Registered User
    Join Date
    Sep 2011
    Posts
    15

    Problem

    Problem is solved. In-case anyone else has a similar issue I'll post what I did.

    I really am not quite sure why this fixed it - but I rewrote all my file input using fgets instead of fscanf and it works perfect now (though fscanf did work when I used the same function to test another similar file in a different, simple program (only reading from it once)). I did change some things outside of the function, but it was still crashing until I did this.

    My function for comparison:
    Code:
    bool AdvanceFilePastToken(FILE* file, const char* token, char delim)
    {
      bool success;
      char buffer[FILE_BUFFER_SIZE];
      
      success = false;
        
      while (fgets(buffer, FILE_BUFFER_SIZE , file) != NULL)
      {
        ExtractDelimString(buffer, delim);
        
        if (strcmp(buffer, token) == 0)
        {
          success = true;
          break;
        }
      }
      
      return success;
    }
    Thanks again to everyone for all the information and help!
    Salem likes this.

  14. #14
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,263
    Quote Originally Posted by Feversaint View Post
    Could you elaborate a little on that please? I think I understand what buffer overflow is, but how would this be vulnerable to it (I'm relatively new to c). From looking at it I'd guess you're saying that if someone were to provide a file that has over 400 chars on a line, it would overflow? Or is there something more to it?
    The '%s' format specified to *scanf() functions means "extract string" and it stops when it hits whitespace, so the overflow occurs if there is a single token (no interior whitespace) of size 401 bytes or larger. An overflow into a stack-based character buffer is the CLASSIC example of a buffer overflow.

    When you switched from fscanf() to fgets() you did a good thing. However, the behavior won't be the same as before, because as I mentioned, %s stops when it hits whitespace, fgets() stops at the end of the line.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 12
    Last Post: 04-23-2010, 09:15 AM
  2. fscanf causing a crash
    By dougwilliams in forum C Programming
    Replies: 6
    Last Post: 11-18-2007, 04:52 PM
  3. cs major
    By jackstify in forum C++ Programming
    Replies: 12
    Last Post: 07-24-2006, 07:08 PM
  4. Major Windows Software - Are there any Major Players Left?
    By Davros in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 11-12-2004, 05:34 PM
  5. Need major help
    By Unregistered in forum C++ Programming
    Replies: 5
    Last Post: 10-09-2001, 11:04 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21