Security issues aside, what you are trying to do is dynamically allocate a buffer.
You can use 2 approaches.
- Always
malloc
inside your function and document it so that it malloced
result. - Follow the path of some standard library functions, ask the user to pass a pointer to a valid buffer and its size and return the actually copied size. Some of these functions allow you to skip
check
when you pass in the null
buffer, they do not try to allocate it, but instead return the size needed to store the structure.
Believes that you have already implemented approach number 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; }
The advantage of method # 2 is that in many cases the caller can allocate a buffer on the stack, especially if you advertise the maximum required buffer size. Another advantage is that memory management is now fully handled by the client. In a general-purpose library, you do not want to create a client, depending on the specific library allocation scheme.
ANSWER TO COMMENT
If you always want to use the highlighted value in your client code, then I will do this:
char* clientGetPasswordFromLibrary( ) { // in our day and age it 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; }