Re: PAM passwdqc, strict aliasing, and WARNS

From: Jilles Tjoelker <jilles_at_stack.nl>
Date: Sat, 14 Jul 2012 15:12:53 +0200
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
Received on Sat Jul 14 2012 - 11:12:54 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:29 UTC