LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-04-2017, 11:46 PM   #1
yakkmeister
Member
 
Registered: Jan 2005
Location: QLD Australia
Distribution: Debian 10 'Buster'
Posts: 74

Rep: Reputation: 16
C: Segfault after fgets


Hello!

I've been pulling out my hair all day over this segfault issue ...

Following is the code causing the problem:
Code:
void promptUser(char *name, char *pass) {
	printf("inside promptUser\n");//DEBUG
	printf("\nEnter username: ");
	fgets(name,USERNAME_SIZE,stdin);
	
	printf("\nEnter password: ");
	fgets(pass,PASSWORD_SIZE,stdin);
	
	printf("Got user and pass");
	return;
	
}
You'll notice that promptUser expects a pointer for both name and pass which is passed to fgets along with the constant for their size:
Code:
#define USERNAME_SIZE 12
#define PASSWORD_SIZE 64

#define FULL_BUFFER_SIZE 256
promptUser is called from readFile:
Code:
void readFile(const char *filename, char *user, char *pass, const char *cryptoKey){
	const char appendMode[] = "a+";
	char buffer[FULL_BUFFER_SIZE];
	FILE *FilePointer;
	
	printf("inside readFile\n");//DEBUG
	

	FilePointer = fopen(filename, appendMode);
	if(!FilePointer){
		promptUser(user, pass);

		memset(buffer, '\0', FULL_BUFFER_SIZE);	// ensure we have a null terminator
		b64_encode(user, buffer, cryptoKey);		// encrypt username
		fputs(buffer, FilePointer);			// write it to file
		fputc('\n', FilePointer);			// write newline character
	
		memset(buffer, '\0', FULL_BUFFER_SIZE);	// clear buffer with null terminator
		b64_encode(user, buffer, cryptoKey);		// encrypt password
		fputs(buffer, FilePointer);			// write it to file
		
		rewind(FilePointer);				// going back to the start
	}

	fgets(user, USERNAME_SIZE, FilePointer);	// read encoded username
	user[strcspn(user, "\n")] = 0;			// strip \n
	memset(buffer, '\0', FULL_BUFFER_SIZE);	// ensure we have a null terminator
	b64_decode(user, buffer, cryptoKey);		// decrypt username
	strcpy(user, buffer);				// copy buffer to username
	
	fgets(pass, PASSWORD_SIZE, FilePointer);	// read encoded password
	pass[strcspn(pass, "\n")] = 0;			// strip \n
	memset(buffer, '\0', FULL_BUFFER_SIZE);	// ensure we have a null terminator
	b64_decode(pass, buffer, cryptoKey);		// decrypt password
	strcpy(pass, buffer);				// copy buffer to password
	
	fclose(FilePointer);
	
}
So readFile sends promptUser the pointer to user and pass, which it gets from main(snippet):

Code:
	const char filename[] = "/filename.here";
	const char localKey[] = "a local key goes here";

	char user[USERNAME_SIZE];
	char pass[PASSWORD_SIZE];

	memset(user, '\0', USERNAME_SIZE);
	memset(pass, '\0', PASSWORD_SIZE);

	readFile(filename, user, pass, localKey);
I have attempted to use scanf as well; same problem.

I have used the following input:
Code:
Enter username: 123456

Enter password: 123456789
Code:
Enter username: harry

Enter password: sigfried
"Segmentation fault" immediately follows the second input and will follow the first if I comment out the second input.
I had a printf("debug") after the second fgets to help find where the issue was occurring, so I'm very confident it's there.

I recognise that the segfault is usually because the input to scanf/fgets has attempted to write outside the bounds of the array pointed to, yet I don't see how that's happening here.

Any help is greatly appreciated.

some notes:
I know return is superfluous in promptUser - I'll probably remove it
I know I encode then decode the same data - promptUser should only ever be used the first time this code is run (or if the username/password file is removed) so the performance hit shouldn't matter.
 
Old 04-05-2017, 01:06 AM   #2
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 16,200

Rep: Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419
try to debug your code.
 
1 members found this post helpful.
Old 04-05-2017, 01:33 AM   #3
yakkmeister
Member
 
Registered: Jan 2005
Location: QLD Australia
Distribution: Debian 10 'Buster'
Posts: 74

Original Poster
Rep: Reputation: 16
I've been plugging away at this problem and made some changes;

I have added:
strcspn() calls to clean up trailing \n before exiting promptUser
if(FilePointer == NULL) check - that was a derp - and some errno goodness.

Backtracing the segfault was basically unenlightening but I did find that the program had somehow moved to an fputs call before exiting the promptUser function ... very weird ... which is why I double-checked the FilePointer == NULL business.
Lo, and behold! There's a problem with permissions on the system.

I had assumed that this code wouldn't need any special attention to permissions as it's being run in a local directory by the same use as has compiled and run the code.

Any ideas on that would be tops.
 
Old 04-05-2017, 02:56 AM   #4
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=14, FreeBSD_12{.0|.1}
Posts: 5,573
Blog Entries: 11

Rep: Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588
While pan64's suggestion to debug your code may be short, I do not think it was intended to be rude.

The example posted is complete and simple enough to yield to ordinary debugging methods. Try to isolate the line or function that is responsible for the segfault and look closely at the validity of your buffer pointers, their size and each use.

Quote:
Originally Posted by yakkmeister View Post
Backtracing the segfault was basically unenlightening but I did find that the program had somehow moved to an fputs call before exiting the promptUser function ... very weird ... which is why I double-checked the FilePointer == NULL business.
That is not weird, it is however a big clue! Think about what you are seeing...

Quote:
Originally Posted by yakkmeister View Post
Lo, and behold! There's a problem with permissions on the system.

I had assumed that this code wouldn't need any special attention to permissions as it's being run in a local directory by the same use as has compiled and run the code.
Please elaborate on that, what do you see that makes you suspect permission problems?

Last edited by astrogeek; 04-05-2017 at 03:07 AM.
 
Old 04-05-2017, 03:13 AM   #5
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 16,200

Rep: Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419Reputation: 5419
you need to compile/link your code with debug option (in general -g) and run it using a debugger, like ddd https://www.gnu.org/software/ddd/ (or command line version: gdb). You can inspect your variables, check the stack easily (and post related info if unclear).

from the other hand you may try valgrind too to catch such kind of issues.
 
2 members found this post helpful.
Old 04-05-2017, 03:28 AM   #6
yakkmeister
Member
 
Registered: Jan 2005
Location: QLD Australia
Distribution: Debian 10 'Buster'
Posts: 74

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by pan64 View Post
you need to compile/link your code with debug option (in general -g) and run it using a debugger, like ddd https://www.gnu.org/software/ddd/ (or command line version: gdb). You can inspect your variables, check the stack easily (and post related info if unclear).

from the other hand you may try valgrind too to catch such kind of issues.
I guess you missed my previous response where I backtraced it?
I used gdb and checked all the frames.
 
Old 04-05-2017, 03:35 AM   #7
yakkmeister
Member
 
Registered: Jan 2005
Location: QLD Australia
Distribution: Debian 10 'Buster'
Posts: 74

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by astrogeek View Post
The example posted is complete and simple enough to yield to ordinary debugging methods. Try to isolate the line or function that is responsible for the segfault and look closely at the validity of your buffer pointers, their size and each use.
Unless there's something there that I'm missing, they look fine ...

Quote:
Originally Posted by astrogeek View Post
That is not weird, it is however a big clue! Think about what you are seeing...
It's not weird? Why? How can the program execute something it hasn't gotten to yet?

Quote:
Originally Posted by astrogeek View Post
Please elaborate on that, what do you see that makes you suspect permission problems?
I used errno after an if(FilePointer == NULL) check.
I put that in the previous reply.

[EDIT]: Oh, I should add that the errno result literally said that the process did not have permission to access/create the file.
Since the file didn't exist and wasn't created, any call to fputs, etc, is going to definitely segfault.

Last edited by yakkmeister; 04-05-2017 at 04:40 AM. Reason: adding relevant information
 
Old 04-05-2017, 04:41 AM   #8
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,149

Rep: Reputation: 1523Reputation: 1523Reputation: 1523Reputation: 1523Reputation: 1523Reputation: 1523Reputation: 1523Reputation: 1523Reputation: 1523Reputation: 1523Reputation: 1523
My suggestions:
1. Use these flags when compile: -Wall -Wextra -pedantic -Werror
2. Add these lines into readFile:
Code:
    FilePointer = fopen(filename, appendMode);
    if (FilePointer==NULL) {
        fprintf (stderr, "*** error opening file '%s' mode '%s' errno=%d: %s\n",
            filename, appendMode, errno, strerror (errno));
        exit (1);
    }
 
1 members found this post helpful.
Old 04-05-2017, 04:49 AM   #9
yakkmeister
Member
 
Registered: Jan 2005
Location: QLD Australia
Distribution: Debian 10 'Buster'
Posts: 74

Original Poster
Rep: Reputation: 16
I'm marking this as solved.

I noticed that I n00b'd the filename.

I used:
Code:
const char filename[] = "/filename.here";
What I needed was:
Code:
const char filename[] = "./filename.here"; //or
const char filename[] = "filename.here";
 
Old 04-05-2017, 04:50 AM   #10
yakkmeister
Member
 
Registered: Jan 2005
Location: QLD Australia
Distribution: Debian 10 'Buster'
Posts: 74

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by NevemTeve View Post
My suggestions:
1. Use these flags when compile: -Wall -Wextra -pedantic -Werror
2. Add these lines into readFile:
Code:
    FilePointer = fopen(filename, appendMode);
    if (FilePointer==NULL) {
        fprintf (stderr, "*** error opening file '%s' mode '%s' errno=%d: %s\n",
            filename, appendMode, errno, strerror (errno));
        exit (1);
    }
Already there; My actual mistake was far dumber ...
 
Old 04-05-2017, 10:19 PM   #11
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=14, FreeBSD_12{.0|.1}
Posts: 5,573
Blog Entries: 11

Rep: Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588Reputation: 3588
Quote:
Originally Posted by yakkmeister View Post
It's not weird? Why? How can the program execute something it hasn't gotten to yet?
Well of course it can't! That you thought that it did do so was the clue!

Quote:
Originally Posted by yakkmeister View Post
I used errno after an if(FilePointer == NULL) check.
I put that in the previous reply.

[EDIT]: Oh, I should add that the errno result literally said that the process did not have permission to access/create the file.
Since the file didn't exist and wasn't created, any call to fputs, etc, is going to definitely segfault.
Yes, that would have been important to include when explaining the permission comment.

All's well that ends well, glad that you got it resolved!
 
  


Reply

Tags
c/c++, pointers, segfault


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
fgets problem sree_ec Programming 4 12-13-2010 12:03 AM
fgets on socket nc3b Programming 2 05-14-2007 07:54 AM
fgets() problems in C AMMullan Programming 4 03-12-2004 04:39 AM
fgets h/w Programming 23 12-21-2003 06:20 PM
fgets vs gets cxel91a Programming 2 12-01-2003 12:36 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:06 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration