Thread: Help with my function (Heh)

  1. #1
    Registered User
    Join Date
    Jan 2006
    Posts
    9

    Help with my function (Heh)

    This code splits 'source' into tokens of nick, ident and host.
    It works and compiles without errors (using gcc -W -Wall).

    However, if i change the *source to "[email protected] .192.168.0.1.com" it segfaults (buffer overflow?), but the compiler still compiles it without any errors..

    Please take in consideration when you're replying that I'm very new to C and still learning the basics.

    Any takers?

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char 	*source = "[email protected]";
    
    	char 	*host;
    	char 	*nick; 
    	char 	*ident;
    	int 	i = 0;
    	host = source;
    
      	/* nick */
     	while (host[i] != '!') 	{
    		nick[i] = host[i];
    		i++;
    	}
    	int nicklen = (size_t) strlen(nick);
    	ident[nicklen] = '\0'; // null terminate
    
    	host += nicklen +1; // removes the nick + ! from host
    
    	/* ident */
     	i = 0;
    	while (host[i] != '@') 	{
    		ident[i] = host[i];
    		i++;
    	}	
    	int identlen = (size_t) strlen(ident);
    	ident[identlen] = '\0'; // null terminate
    
    	host += (size_t) identlen +1; // removes the ident + @ from host
    
    	/* ..and the remains of *host is the hostname */	
    
    	printf(" nick: %s\n", nick);
    	printf("ident: %s\n", ident);
    	printf(" host: %s\n", host);
        
        return 0;
    }

  2. #2
    Registered User
    Join Date
    Mar 2005
    Posts
    135
    One of the problems I see is that you haven't initialized "nick" with memory in order for it to hold the values it's being assigned to by host in the first while loop. I see more errors, "ident" is also not being initialized with memory before being used. It looks to me like you need to study up some more on pointers, check th FAQ for a brief introduction.

  3. #3
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Code:
    ident[nicklen] = '\0'; // This is your buffer overflow.
    nicklen is equal to the size of your array based on the statement before this. And as you might know, the size of an array is not an index in the array as it goes from 0 to (size-1)

    Now this would matter ofcourse if you were allocating memory into these pointers, but you aren't. You have to use malloc(). It's in the C programming tutorials.
    Sent from my iPadŽ

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Merely as an aside -- the other items mentioned are the root of your problem -- but this just strikes me as curious:
    Code:
    int identlen = (size_t) strlen(ident);
    Since strlen returns a size_t, why would you explicitly cast the return value from a size_t to a size_t, and then assign it to an int?

    It seems as though you're afraid of using a size_t value due to unfamiliarity, perhaps, but then using a cast with something you are unfamiliar with seems a dangerous proposition.


    And are you using C99 or C++ for the declarations that follow statements?

    [edit]By the way, I might go with something like this to start.
    Code:
    #include <stdio.h>
    
    int main(void)
    {
       const char source[] = "[email protected]";
       char host[128], nick[128], ident[128];
       if ( sscanf(source, "%127[^!]!%127[^@]@%127[^\n]", nick, ident, host) == 3 )
       {
          printf(" nick: %s\n", nick);
          printf("ident: %s\n", ident);
          printf(" host: %s\n", host);
       }
       return 0;
    }
    
    /* my output
     nick: nick
    ident: ident
     host: a.random.long.stupid.host.192.168.0.1.com
    */
    Last edited by Dave_Sinkula; 03-21-2006 at 09:32 PM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    Registered User
    Join Date
    Jan 2006
    Posts
    9
    Thank you all for your quick reply and pointers!

    I've updated the code and it works very well.. almost.

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main(void)
    {
    	char	*source		= "[email protected]";
    
    	int		maxnicklen	= 32;
    	int		maxidlen	= 32;
    
    	char	*host		= malloc(sizeof source);
    	char	*nick		= malloc(maxnicklen); 
    	char	*ident		= malloc(maxidlen);
    
    	int		i			= 0;
    
    	host = source;
    
    	/* nick */
    	while ((host[i] != '!') && (i < maxnicklen))  
    	{
    		nick[i] = host[i];
    		i++;
    	}
    
    	int nicklen = strlen(nick);
    	ident[nicklen] = '\0';
    	host += nicklen +1;
    
    	/* ident */
    	i = 0;
    	while ((host[i] != '@') && (i < maxidlen)) 
    	{
    		ident[i] = host[i];
    		i++;
    	}
    
    	int identlen = strlen(ident);
    	ident[identlen] = '\0'; 
    	host += identlen +1;
    
    	printf("%s (%s @ %s)\n", nick, ident, host);
    
    	/*
    	free(host);
    	free(nick);
    	free(ident);
    	*/
    
    	return 0;
    
    }
    However, when I add "free (host);" (and nick, ident) it segfaults! Any ideas?

    Dave_Sinkula: That sscanf is pretty cool, thanks.

    (Btw, my indenting isn't as bad as it might look on the forum :P)
    Last edited by phatsam; 03-23-2006 at 09:48 AM.

  6. #6
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Code:
    int nicklen = strlen(nick);
    nick[nicklen] = '\0';
    What do you think the strlen of nick is if nick isn't null terminated? I made a few changes to your code so it works properly. I'm also not sure why you're getting segmentation faults, but I'd guess it's due to the fact that you're out of bounds with your null characters.
    Code:
    #include <stdio.h>
    #include <string.h>
    
    const int maxnicklen	= 32;
    const int maxidlen	= 32;
    
    int main(void)
    {
       char *source = "[email protected]";
    
       char *host = malloc(strlen(source));
       char *nick = malloc(maxnicklen); 
       char *ident = malloc(maxidlen);
    	
       int i = 0;
    
       host = source;
    
       while (*host != '!' && i < maxnicklen) {
        nick[i] = *host;
        i++;
        host++;
       }
    	
       nick[i] = '\0';
       host++;
       
       i = 0;
       while (*host != '@' && i < maxidlen) {
         ident[i] = *host;
         i++;
         host++;
       }
    	
       ident[i] = '\0'; 
       host++;
    	
       printf("Nick:  %s \n"
              "Ident: %s \n"
              "Host:  %s \n", 
              nick, ident, host);
    	
       free(host);
       free(nick);
       free(ident);
    	
       return 0;
    }
    Take a look at this and see what it's doing differently. I kept it along the lines of what you were doing and made as few changes as possible. In reality, you'd probably go with something like Dave posted.
    Last edited by SlyMaelstrom; 03-23-2006 at 10:31 AM.
    Sent from my iPadŽ

  7. #7
    Registered User
    Join Date
    Jan 2006
    Posts
    9
    Woah, that's nice and clean.
    Thanks SlyMaelstrom.

    And yeah, I will go with what Dave posted, but I just wanted to finish my own fuction for learing purposes

    Thanks for now.

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    @ SlyMaelstrom
    I count at least 5 bugs in your code.

    > char *host = malloc(strlen(source));
    1. Didn't include stdlib.h
    2. Didn't account for the \0

    > host = source;
    This doesn't copy the string, it does however
    3. introduce a memory leak.
    4. crash when you try and free it later on, since you're freeing what you didn't malloc.

    > while (*host != '!' && i < maxnicklen)
    5. If you exit on the 2nd condition, the \0 character which follows is out of bounds.
    This is repeated in the next loop as well (so perhaps 6 altogether?)
    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.

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Sly's code is broken.
    Code:
    while (*host != '@' && i < maxidlen) {
         ident[i] = *host;
         i++;
         host++;
    }
    	
    ident[i] = '\0';
    What happens when i is (in this case) 31 at the start of the loop, and you still haven't found a @? BadThings(TM), that's what.


    Quzah.
    Hope is the first step on the road to disappointment.

  10. #10
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Quote Originally Posted by quzah
    What happens when i is (in this case) 31 at the start of the loop, and you still haven't found a @? BadThings(TM), that's what.

    Mmmm good point. Threw it together without seeing that. I'll credit myself for that discovery and put your name in the special thanks list.
    Sent from my iPadŽ

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  2. Seg Fault in Compare Function
    By tytelizgal in forum C Programming
    Replies: 1
    Last Post: 10-25-2008, 03:06 PM
  3. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 01:01 AM
  4. Brand new to C need favor
    By dontknowc in forum C Programming
    Replies: 5
    Last Post: 09-21-2007, 10:08 AM
  5. const at the end of a sub routine?
    By Kleid-0 in forum C++ Programming
    Replies: 14
    Last Post: 10-23-2005, 06:44 PM