change_password resource cleanup?
Greg Hudson
ghudson at mit.edu
Sat Jun 28 02:22:31 EDT 2025
On 6/28/25 00:50, Joonas Tuomisto wrote:
> krb5_change_password() returns the result_code_string and result_string
> krb5_data structures. Are you supposed to free() them - or I suppose more
> specifically, krb5_free_data() them after use?
They should be freed with krb5_free_data_contents() when the caller is
done with them.
krb5_free_data() would free the krb5_data pointer itself, which would be
asymmetric (the pointer is supplied by the caller and not allocated by
krb5_change_password()) and often a memory violation.
> The documentation for krb5_chpw_message() explicitly calls out that you
> should krb5_free_string() its message_out. For krb5_change_password() it
> does not.
We usually document freeing requirements for libkrb5 function outputs,
and it is indeed missing for krb5_change_password(). I have made a note
to fix this. (Also missing: result_code_string may be null, although
result_string is required.)
> Are these krb5_free_* functions always safe to call or should you only
> assume the structs exist (and require cleanup) when e.g.
> krb5_change_password() returns with result_code set?
There are early exit paths from krb5_change_password() that do not set
*result_code_string or *result_string. This is not really ideal; we
generally try to initialize output arguments in library APIs, but a lot
of libkrb5 was written before that became a common practice. I have
made a note to fix this.
(libgssapi_krb5 is much, much better about initializing output arguments
along all exit paths.)
krb5_free_*() functions are okay to call with null pointers, or with
structures containing null pointers (e.g. krb5_free_data_contents() on a
krb5_data structure whose data element is null).
> My code now has if (retval) ... if (result_code) ... sprinkled and I can
> already see myself how you could easily end up with resource leaks with C
> and different code paths. A common cleanup path helps.
In spite of krb5_change_password() not always setting output arguments,
the following should be safe:
krb5_error_code ret;
krb5_data result_code_string = { 0 }, result_string = { 0 };
...
ret = krb5_change_password(context, ..., &result_code_string,
&result_string);
if (ret)
goto cleanup;
...
cleanup:
krb5_free_data_contents(context, &result_code_string);
krb5_free_data_contents(context, &result_string);
More information about the krbdev
mailing list