Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C: Returning string from function

Tags:

c

string

I have a function that returns a string:

const *char getMyPassword()
{
    return "mysecretpassword";
}

Well, it worked perfectly, but I discovered that if I would run "strings" on Unix systems it shows up in the list.. not good.

What is the easiest possible way to replace it? The function sits in a library and I want to keep it flexible. I now started mallocing within the function and the string in strings disappeared. However, when would I free it again?

char * getMyPassword()
{
unsigned char arr[] = { 'p', 'a', 's', 's', 'w', 'o', 'r' , 'd', '\0' };
char *return_arr = malloc(sizeof(arr));
strcpy(return_arr, arr);
return return_arr;

}

If I was to malloc before and pass a pointer, then how could I have known the size before as the passwords size is only known within the function?

As a plan B I could pass a huge array, but that seems not very elegant. How should I approach this?

EDIT: I added the strcpy(return_arr, arr). I actually had it in the original code, but forgot it in here.

like image 221
Frank Vilea Avatar asked Oct 11 '11 22:10

Frank Vilea


People also ask

Can I return a string from a function in C?

Strings in C are arrays of char elements, so we can't really return a string - we must return a pointer to the first element of the string. All forms are perfectly valid.

What does char * mean in C?

In C, char* means a pointer to a character. Strings are an array of characters eliminated by the null character in C.

How do you print a string in C?

using printf() If we want to do a string output in C stored in memory and we want to output it as it is, then we can use the printf() function. This function, like scanf() uses the access specifier %s to output strings. The complete syntax for this method is: printf("%s", char *s);

Can you return a char in C?

Since int and char are inter-operable, you can return a char value by typecasting it to int.


1 Answers

Security issues aside, what you are trying to do is dynamically allocate buffer.

You can take 2 approaches.

  1. Always malloc inside your function and document it that it returns malloced result.
  2. Follow the road of some standard library functions, require that user pass a pointer to a valid buffer and its size and return the size actually copied. Some of these functions allow the check pass, when you pass in a null buffer, they do not try to allocate it, but instead return the size that is required to hold the structure.

Looks to me that you've already implemented approach #1.

For approach #2 use this signature:

int getMyPassword( char* buffer, size_t buff_size, size_t* p_num_copied )
{
  unsigned char arr[] = { 'p', 'a', 's', 's', 'w', 'o', 'r' , 'd', '\0' };

  if ( buffer == 0 )
  {
    *p_num_copied = sizeof(arr);
    return SUCCESS;
  }

  if ( buff_size < sizeof(arr) )
  {
    *p_num_copied = sizeof(arr);
    return BUFFER_TOO_SMALL;
  }

  memcpy( buffer, arr, sizeof(arr) );

  *p_num_copied = sizeof( arr );

  return SUCCESS;
}

Advantage of method #2 is that the caller, in many cases, may allocate the buffer on stack, especially if you advertise the maximum required buffer size. Another advantage is that memory management is now completely handled by client. In general purpose library you don't want to make a client depending on a particular library memory allocation schema.

IN REPLY TO COMMENT

If you always want to use allocated value in your client code, then this is how I would do this:

char* clientGetPasswordFromLibrary( )
{
  // in our day and age it's fine to allocate this much on stack
  char buffer[256];
  size_t num_copied;

  int status = getMyPassword( buffer, sizeof(buffer), &num_copied );

  char* ret_val = NULL;

  if ( status == BUFFER_TOO_SMALL )
  {
    ret_val = malloc( num_copied );

    if ( ret_val == NULL )
    {
      return NULL;
    }

    getMyPassword( ret_val, num_copied, &num_copied );
  }
  else
  {
    ret_val = malloc( num_copied );

    if ( ret_val == NULL )
    {
      return NULL;
    }

    memcpy( ret_val, buffer, num_copied );
  }

  return ret_val;
}
like image 52
Alexander Pogrebnyak Avatar answered Oct 26 '22 23:10

Alexander Pogrebnyak