Search code examples
csegmentation-faultfreemtrace

Segmentation fault after free variables which are used return in function


I need the last 2 column in ipv6 address. (2001:1234:asdd:xeed:212:4b00:61) --> (4b0061) also i need to know how to free this return of ipv6_parser function.

it is given "Segmentation fault" when i am trying to free result.

char* ipv6_parser(char* str){
    char *ret = malloc(sizeof(str));

  ret = str;
  ret = strtok(ret,":");
  int i ;
  for (i=0;i<5;i++){
        ret = strtok(NULL, ":");
  }
  char *last = strtok(NULL, ":");
  sprintf(ret,"%s%s",ret,last);

  return ret;
}

int main(){
  mtrace();

    char *str=strdup("2001:1234:asdd:xeed:212:4b00:61");
    char* result    = ipv6_parser(str); 
    printf("\nResult - %s\n",result);
  free(result);
  free(str);
return(0);
}

Solution

    • ret = str; is not copying the string but assigning the input pointer itself to ret and causing memory leak.
    • You cannot use sizeof(str) to determine the length of string.
    • sprintf(ret,"%s%s",ret,last); invokes undefined behavior by copying between overwrapped objects.

    Try this:

    char* ipv6_parser(const char* str){
      char *ret = malloc(strlen(str) + 1);
      if (ret == NULL){
        perror("malloc ret");
        return NULL;
      }
      char *ret_buffer = ret; /* store where the buffer is to free it after using */
    
      strcpy(ret,str);
      ret = strtok(ret,":");
      int i;
      for (i=0;i<5;i++){
        ret = strtok(NULL, ":");
      }
      char *last = strtok(NULL, ":");
      char *final_ret = malloc(strlen(ret) + strlen(last) + 1);
      if (final_ret == NULL){
        perror("malloc final_ret");
        free(ret_buffer);
        return NULL;
      }
      sprintf(final_ret,"%s%s",ret,last);
      free(ret_buffer);
    
      return final_ret;
    }