On 7/15/2012 3:56 AM, pozz wrote:
> Il 12/07/2012 17:08, Eric Sosman ha scritto:
>> On 7/12/2012 10:42 AM, pozz wrote:
>>> Il 11/07/2012 17:59, Eric Sosman ha scritto:
>>>> A problem with the approach you've outlined is that the
>>>> checksum computation will include the values of any padding
>>>> bytes -- the size of `z' in your example almost begs for some
>>>> padding bytes to be inserted. Since padding bytes are not
>>>> necessarily preserved when assigning structs or even when
>>>> assigning to struct elements, a checksum that includes padding
>>>> bytes is unlikely to be very useful. Similar concerns apply to
>>>> bit-field elements: The values of un-named bits are not necessarily
>>>> preserved. For that matter, if `z' holds a string (as opposed to a
>>>> generic batch of chars), the bytes after '\0' should probably be
>>>> omitted from a checksum since they're not part of the "value."
>>>
>>> Yes, they are considerations I also made. In my application (running on
>>> a single processor), I have to read/write the struct from/to a file and
>>> use it in memory. I'm not interested in a standard format file (its a
>>> custom configuration for the application) and I'll never need to
>>> read/write the struct on a different processor.
>>>
>>> I know other better standard file formats for configuration settings are
>>> available (INI, XML, ...), but I'm working on an embedded simple
>>> processor and I don't want to increase the complexity of the software
>>> just for the configuration.
>>
>> The fact that you intend to use the struct only locally and
>> only on one processor doesn't change anything: Padding bytes will
>> still contain random and potentially non-constant garbage, bytes
>> after the '\0' terminating a string are probably garbage, and so
>> on. It's unlikely, but the mere act of storing the checksum into
>> the struct could in principle change the padding bytes -- if it
>> does, the checksum is self-invalidating!
>
> So a possible solution is to store the checksum outside the struct as
> a different variable.
Yes, as I suggested in the very next paragraph:
>> If you want to write a struct and a checksum to a file and
>> verify the checksum when you read it back, keep the checksum as
>> a separate variable and don't put it inside the struct.
>
> Could I ignore the "randomness" of the padding bytes? I read that
> the padding bytes can be randomly changed even assigning a value to a
> field of the struct.
Now, *where* could you have read such a thing?
> My application should work in this way:
>
> - at startup, read the configuration file, calculate and verify the
> checksum: if it isn't correct, use a default struct;
Right: You'd read the struct's bytes directly into an instance
of itself using fread(), say, rather than making field assignments.
Then you'd read the stored checksum into an independent variable,
re-calculate the struct's checksum, and compare. It's your choice
what to do about a mismatch.
> - when a field changes (after assigning it the new value), calculate
> the new checksum and save both (struct and checksum) to the file;
Right again: Calculate the new checksum, store it in a free-
standing variable, and write the bytes of both to the file. Again,
it's up to you to decide how frequently you want to do this: On
every change, only at program shutdown, or something in between.
> - during the normal execution of the application, the fields of the
> struct are accessed many times.
>
> In this situation, could I calculate the checksum on the entire
> memory area of the struct (with padding bytes)? I read the padding
> bytes can be randomly changed when a value is assigned to a field, but
> in this case a re-calculate the checksum. What happens if I access a
> field? Also for read operations the padding bytes could be changed?
Padding bytes are "vulnerable" when their fellow travellers are
stored to (6.2.6.1p6). There's no similar language for read accesses,
which I interpret as meaning reads won't change them. Note that this
applies only to the padding in the instance that's being read; if you
copy a padded struct from one instance to another
struct padded s1 = ...;
// Suppose the padding bytes in s1 have values p1,p2,...
struct padded s2 = s1;
// s1's padding is still p1,p2,... but s2's can differ.
.... the padding in the original doesn't change, but the padding in
the copy need not agree with it. So when you're moving data back
and forth to files, be sure to do the checksum calculations on the
exact same struct instance that you use for the I/O, not on a copy.
--
Eric Sosman
d