Cast alignment warnings
Russ Allbery
rra at stanford.edu
Mon Aug 1 22:35:34 UTC 2011
Julien ÉLIE <julien at trigofacile.com> writes:
> Ah, I did not know a cast was actually performed (with a rewrite of the
> memory present in the size of the new type).
Well, sort of -- I'm not sure if I'm misunderstanding your phrasing or
your mental model. We take the address of the storage for a char (on the
stack) and then pass it into a function that wants a pointer to an
integer. The cast doesn't actually *do* anything other than silence the
(correct) resulting warning; it's still the same address. Inside sscanf,
you have loss of information: it has no idea that the pointer was
originally to a char and takes our word for it that it is pointing to an
integer's worth of storage, and then writes an integer's worth of data
into that location.
> Anyway, it makes sense. It could also have only be a read: sscanf()
> would read the size of the new type (and maybe segfaulting if it exceeds
> what the program is allowed to access).
I don't think sscanf ever looks at the contents of the pointers it's
passed. It just blindly writes the results to them and assumes they're
valid storage locations for the data types that you said to put there.
In this case, a segfault is unlikely, since the pointer will be to the
middle of stack space. Most likely we'll just overwrite three bytes of
some neighboring variable, which would go unnoticed if that variable is
only used later on. Worst case is that it will overwrite some part of the
stack frame for the fuction, leading to completely unpredictable results.
> So it appears that -Wcast-align may be useful :-)
> Would it be OK to cast the network calls to void * as you suggested, so as
> to keep -Wcast-align in our checks?
Yeah, I suppose that also works. I kind of hate to clutter the code with
that sort of cast, but if we find real bugs, it's useful.
> It would therefore require a subtle use of ntohs/htons calls.
Yeah. But it's a self-created problem due to taking the address of a char
and then telling another function to write an integer in it. If one just
writes to an integer and then stores the value of the integer in a char,
the compiler will add all the necessary conversion automatically.
> Hm, it should normally be ntohi/itohn for integers, shouldn't it? But
> these functions are not necessarily present...
ntohs/htons and ntohl/htonl are intended for use with wire protocols where
you know exactly how many bits you're dealing with, so you have to pick
the 16-bit or 32-bit version. Integers in C can be 16, 32, or 64 bits
depending on the architecture, so you couldn't have a reliable network
protocol that used the local integer size.
(You can tell how old those functions are from the fact that the 32-bit
version is the "long" one.)
--
Russ Allbery (rra at stanford.edu) <http://www.eyrie.org/~eagle/>
Please send questions to the list rather than mailing me directly.
<http://www.eyrie.org/~eagle/faqs/questions.html> explains why.
More information about the inn-workers
mailing list