PAM passwdqc, strict aliasing, and WARNS
Jilles Tjoelker
jilles at stack.nl
Sat Jul 14 13:12:54 UTC 2012
On Fri, Jul 13, 2012 at 04:14:17PM -0600, Justin T. Gibbs wrote:
> Someone who has yet to confess added -Werror to the global CFLAGS
> (via /etc/make.conf) for one of our systems at work. Before I
> figured out that this was the cause of builds failing, I hacked up
> pam_passwdc to resolve the problem. This gets the module to
> WARNS=2, but to go farther, the "logically const" issues with this
> code will need to be sorted out.
> Is this change worth committing? Is this the best way to resolve
> the strict aliasing issues in this code?
The prototype of pam_get_item() is
int pam_get_item(const pam_handle_t *pamh, int item_type, const void **item);
Therefore, you should pass a pointer to a const void pointer as the last
argument. You can then convert the const void pointer to the desired
type.
For example:
const void *item;
const struct pam_conv *conv;
result = pam_get_item(pamh, PAM_CONV, &item);
conv = item;
Passing something like a pointer to a 'const struct pam_conv *' to
pam_get_item() will cause a strict-aliasing violation because
pam_get_item() will attempt to store a value into an object of declared
type 'const struct pam_conv *' using an lvalue of type 'const void *'.
In both C99 and C11, these rules are in 6.5 Expressions.
In the case of const struct pam_conv *, the union approach violates the
C standard because the C standard does not guarantee that all object
pointers have the same representation. The conversion might be
non-trivial and a "type-pun" may not work properly. However, in almost
all real machines the conversion is trivial.
Some compilers may still consider the union approach a strict-aliasing
violation. In any case, I think it is a bit ugly and should be avoided
when possible (like here).
--
Jilles Tjoelker
More information about the freebsd-current
mailing list