GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 17-Sep-2005, 09:29
Brass Monkey Brass Monkey is offline
New Member
 
Join Date: Sep 2005
Posts: 1
Brass Monkey is on a distinguished road

scanf and Check Failure #2 error


This program is taking input and spitting it back out. It is only to accept a single character a-z. then print it back out and wait for me to enter any number so I can see what was printed then end the program. After entering a valid number and seeing the result I enter a number to end the program I get the following error:

Run-Time Check Failure #2 - Stack around the variable 'stateRank' was corrupted.

I'm not sure why, can you guys clue me in on the answer?

CPP / C++ / C Code:
int main()
{
	int result = 0;
	int testVar;
	char stateRank;
	char dump;
	
	while (result != 1)
	{
		printf("Enter Move: ");
		result = scanf("%[a-z]", &stateRank);

		while((dump = getchar()) != '\n' && dump != EOF)
		{
		}
	}
	printf("%c, %d\n", stateRank, result);
	scanf("%d", &testVar);

  return 0;
}
  #2  
Old 17-Sep-2005, 11:31
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,720
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
Quote:
Originally Posted by Brass Monkey

CPP / C++ / C Code:
.
	char stateRank;
.	
		result = scanf("%[a-z]", &stateRank);
.


The "%[" format specifier causes this to happen (quoting from the C standard):
Quote:
[ Matches a nonempty sequence of characters from a set of expected characters (the scanset ). The corresponding argument shall be a pointer to the initial character of an array large enough to accept the sequence and a terminating null character, which will be added automatically.

So the argument must be the address of an array large enough to hold all of the input characters (between a and z) entered by the user, plus one to hold the terminating '\0'. In other words, if you enter one char, say, 'x', scanf stores this at the address of stateRank, then stores a '\0' in the next address. The next address does not belong to you. (In general, the only data addresses that belong to you are addresses of non-const declared variables, or locations within blocks of memory obtained from malloc() or its cousins.) Some compilers assign addresses for automatic variables on integer boundaries, some pack them in, some do other things. Any given compiler might not choke on this bug, but it is a bug.

I tested the program on my Windows box (Borland, Microsoft, and GNU compilers) and my Linux box (GNU compiler).

I couldn't make the program crash by entering a single character, but I got a crash every time by entering more than 13 'x' characters (or 13 anythings between a and z). The scanf function is not safe for reading strings with %s or with %[]. Remember, scanf only knows what you give it as arguments. It doesn't know if your pointer points to enough legal memory to handle all possible user input.

You were lucky that you saw the error now. This is a hidden time bomb waiting to wreak havoc some day. This is precisely the kind of "buffer overflow" bug that is exploited by script kiddies and other malefactors. Typically it is not caught at compile time, and may or may not be discovered by testing, depending on the experience and skills of the tester(s).

One possible fix for your particular requirements: declare stateRank to be an array of two chars, then use the following scanf:

CPP / C++ / C Code:
.
    result = scanf("%1[a-z]", stateRank);

Now, by putting a limit value of 1 in the format specifier, scanf will store an input char in stateRank[0], and will store '\0' in stateRank[1]. Scanf will always store the '\0', so two chars is the minimum size for stateRank.


Regards,

Dave
Last edited by davekw7x : 17-Sep-2005 at 12:07.
  #3  
Old 17-Sep-2005, 12:47
WaltP's Avatar
WaltP WaltP is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Midwest US
Posts: 3,245
WaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to allWaltP is a name known to all
Or better yet, use getchar() instead of scanf() -- this post and its followup together explain why
__________________

Age is unimportant -- except in cheese
 
 

Recent GIDBlogDeveloping GUIs with wxPython (Part 2) by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Things to Avoid in C/C++ -- gets() , Part 1 WaltP C Programming Language 5 21-Jun-2007 12:13
RSA program fwongmc C Programming Language 11 08-Nov-2004 22:15

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 20:28.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.