473,404 Members | 2,187 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,404 software developers and data experts.

Padding bits and struct assignment

Does struct assignment copy padding bytes? Some compilers do, but
I couldn't find anything in the standard which says they must.

What I need is for any padding bytes to contan initialized values
before fwrite(), to shut up memory debuggers like Valgrind about
writing uninitialized data to the file.

Simplified code:
static const struct S default_value = ...;
struct S s, t;
t = default_value;
for (...) {
s = t;
...modify s and t...;
fwrite(&s, sizeof(s), 1, f);
}

If padding bytes not copied, I guess I could wrap the struct in
union {
struct S s;
char bytes[sizeof(struct S)]
}
and copy that instead of struct S, or memset both s and t after
the declarations. (When Valgrind copies an uninitialized byte
from t to s, it remembers that that byte in s contains and
uninitialized value.)

--
Hallvard
Dec 27 '06 #1
5 4006
Hallvard B Furuseth wrote:
Does struct assignment copy padding bytes? Some compilers do, but
I couldn't find anything in the standard which says they must.
It is not required that padding bytes be copied.

6.2.6 Representations of types
6.2.6.1 General
[...]
6/ When a value is stored in an object of structure or
union type [...] the bytes of the object representation that
correspond to any padding bytes take unspecified values. 42)

42) Thus, for example, structure assignment may be
implemented element-at-a-time or via memcpy.
What I need is for any padding bytes to contan initialized values
before fwrite(), to shut up memory debuggers like Valgrind about
writing uninitialized data to the file.

Simplified code:
static const struct S default_value = ...;
struct S s, t;
t = default_value;
for (...) {
s = t;
...modify s and t...;
fwrite(&s, sizeof(s), 1, f);
}
Hmmm. All the named elements of default_value are initialized,
either explicitly by the initializer or implicitly by virtue of the
static storage duration, but I don't think the guarantee extends to
its padding bytes. Even if the padding bytes are initialized (as
seems likely on common implementations), the assignment to t need
not copy them and may leave the padding bytes in t uninitialized.
You could do memset(&t, 42, sizeof t) first, but even then I don't
think you're completely safe: if the padding bytes of default_value
are uninitialized and the assignment *does* copy them, then the
padding bytes of t wind up "uninitialized," too.
If padding bytes not copied, I guess I could wrap the struct in
union {
struct S s;
char bytes[sizeof(struct S)]
}
and copy that instead of struct S, or memset both s and t after
the declarations. (When Valgrind copies an uninitialized byte
from t to s, it remembers that that byte in s contains and
uninitialized value.)
This may silence the memory monitor, but from C's point of
view I don't think it makes a difference. *Every* assignment
to a struct/union or to any of its members may pollute whatever
padding bytes are present. The memory monitor may no longer see
them as "uninitialized," but they are "potentially garbage"
nonetheless.

The only foolproof method I can think of is unfortunately
icky, and won't work for structs with bit-fields:

struct S s = ...;
unsigned char b[sizeof s];
memset (b, 42, sizeof b);
memcpy (b + offsetof(struct S, e1), &s.e1, sizeof s.e1);
memcpy (b + offsetof(struct S, e2), &s.e2, sizeof s.e2);
...
fwrite (b, sizeof b, 1, f);

.... which would probably be improved by a little table of sizes
and offsets. Given such a table, though, you might choose not
to write the padding bytes out at all.

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 27 '06 #2
Eric Sosman writes:
Hallvard B Furuseth wrote:
>Does struct assignment copy padding bytes? Some compilers do, but
I couldn't find anything in the standard which says they must.

It is not required that padding bytes be copied.

6.2.6 Representations of types
(...)
Thanks. That's what I was not hoping for:-)
>What I need is for any padding bytes to contan initialized values
before fwrite(), to shut up memory debuggers like Valgrind about
writing uninitialized data to the file.
Simplified code:
static const struct S default_value = ...;
(...)

Hmmm. All the named elements of default_value are initialized,
either explicitly by the initializer or implicitly by virtue of the
static storage duration, but I don't think the guarantee extends to
its padding bytes. (...)
Probably true, but Valgrind & co treat static storage as initialized -
at least on the few hosts I have seen. I guess they have no way to tell
the difference between an uninitialized static byte and a static
variable with no initializer.

I think whether I'll use a static will depend on how cumbersome it
gets not to, and how safe the rest of the code gets. Which after
your reply doesn't look too hopeful...
>If padding bytes not copied, I guess I could wrap the struct in
union {
struct S s;
char bytes[sizeof(struct S)]
}
and copy that instead of struct S, or memset both s and t after
the declarations. (When Valgrind copies an uninitialized byte
from t to s, it remembers that that byte in s contains and
uninitialized value.)

This may silence the memory monitor, but from C's point of
view I don't think it makes a difference. *Every* assignment
to a struct/union or to any of its members may pollute whatever
padding bytes are present. The memory monitor may no longer see
them as "uninitialized," but they are "potentially garbage"
nonetheless.
Oh, of course. I stuff nicely initialized data into the union,
then assign to a bitfield or char member in struct, and maybe the
padding bytes in the same word get scrambled:-(

Hmm. That's a problem with security too, if one wants to fwrite()
structs but be sure to not write other internal data in the program.
The only foolproof method I can think of is unfortunately
icky, and won't work for structs with bit-fields:

struct S s = ...;
unsigned char b[sizeof s];
memset (b, 42, sizeof b);
memcpy (b + offsetof(struct S, e1), &s.e1, sizeof s.e1);
memcpy (b + offsetof(struct S, e2), &s.e2, sizeof s.e2);
...
fwrite (b, sizeof b, 1, f);

... which would probably be improved by a little table of sizes
and offsets. Given such a table, though, you might choose not
to write the padding bytes out at all.
Ouch. I don't think I'll be going there just to be Valgrind-safe,
not until it actually complains anyway. After all the code is
correct as C code, it's just Valgrind which gets noisy.

Thanks for the help.

--
Hallvard
Dec 27 '06 #3
Hallvard B Furuseth wrote:
[about writing "uninitialized" padding bytes with fwrite]

Hmm. That's a problem with security too, if one wants to fwrite()
structs but be sure to not write other internal data in the program.
I've seen a related problem that didn't even need padding
bytes. Roughly, the scenario was:

struct {
char first[SIZE];
char last[SIZE];
} name;
strcpy (name.first, "Hallvard");
strcpy (name.last, "Furuseth");
fwrite (&name, sizeof name, 1, stream);

Each strcpy() writes to the first nine bytes of its target
array, but leaves the tail ends untouched (assuming SIZE 9).
Whatever happens to be lying around in those locations gets
written to the output stream; it may or may not be something
that ought to be revealed. In the particular case I ran across,
the telephone numbers of some of my co-workers were visible in
the disk file.

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 27 '06 #4
Eric Sosman wrote:
Hallvard B Furuseth wrote:
>[about writing "uninitialized" padding bytes with fwrite]

Hmm. That's a problem with security too, if one wants to fwrite()
structs but be sure to not write other internal data in the program.

I've seen a related problem that didn't even need padding
bytes. Roughly, the scenario was:

struct {
char first[SIZE];
char last[SIZE];
} name;
strcpy (name.first, "Hallvard");
strcpy (name.last, "Furuseth");
fwrite (&name, sizeof name, 1, stream);

Each strcpy() writes to the first nine bytes of its target
array, but leaves the tail ends untouched (assuming SIZE 9).
Whatever happens to be lying around in those locations gets
written to the output stream; it may or may not be something
that ought to be revealed. In the particular case I ran across,
the telephone numbers of some of my co-workers were visible in
the disk file.
Sounds like an excellent opportunity for strncpy.

strncpy(name.first, "Hallvard", SIZE);
strncpy(name.last, "Furuseth", SIZE);

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Dec 27 '06 #5
CBFalconer wrote:
Eric Sosman wrote:
>Hallvard B Furuseth wrote:
>>[about writing "uninitialized" padding bytes with fwrite]

Hmm. That's a problem with security too, if one wants to fwrite()
structs but be sure to not write other internal data in the program.
I've seen a related problem that didn't even need padding
bytes. Roughly, the scenario was:

struct {
char first[SIZE];
char last[SIZE];
} name;
strcpy (name.first, "Hallvard");
strcpy (name.last, "Furuseth");
fwrite (&name, sizeof name, 1, stream);

Each strcpy() writes to the first nine bytes of its target
array, but leaves the tail ends untouched (assuming SIZE 9).
Whatever happens to be lying around in those locations gets
written to the output stream; it may or may not be something
that ought to be revealed. In the particular case I ran across,
the telephone numbers of some of my co-workers were visible in
the disk file.

Sounds like an excellent opportunity for strncpy.

strncpy(name.first, "Hallvard", SIZE);
strncpy(name.last, "Furuseth", SIZE);
Yes, that was my quick and dirty fix. "Dirty" because a
better solution would have been to devise a file format that
(1) didn't depend on non-portable details like struct layout
and (2) didn't waste time writing and reading useless bytes.
However, I also needed "quick," and since there was a large
number of old-format files kicking around in our own and our
customers' computers ... The desire for "quick" trumped the
distaste for "dirty."

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 27 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Paul_Huang | last post by:
OK, I tried it with a piece of sample code to test the memory padding and alignment and get some weird results. I would appreciate if anybody can help to give a explain. Below is my sample code:...
13
by: Amarendra | last post by:
Folks, This structure padding issue is bothering me now, could not locate a satisfactory answer on clc, so here it goes... I have a structure, given below: typedef struct { int flag; char...
8
by: copx | last post by:
Hi, I remember hearing that the size of a struct can be bigger than the sum of the sizes of its contents. Is that true? For example let's say char is 1 byte and int is 4 byte in this case and...
64
by: yossi.kreinin | last post by:
Hi! There is a system where 0x0 is a valid address, but 0xffffffff isn't. How can null pointers be treated by a compiler (besides the typical "solution" of still using 0x0 for "null")? -...
9
by: edware | last post by:
I want to read header data from a image file, and I have a struct that represent this header. But it seems like my compiler pads the data, resulting that my fread() call won't put the right...
1
by: fdmfdmfdm | last post by:
code like: struct pid_tag{ unsigned int inactive : 1; unsigned int : 1; /* 1 bit of padding */ unsigned int refcount : 6; unsigned int : 0; /* pad to next word boundary...
14
by: Francine.Neary | last post by:
Consider the following situation. I have a large static array s of structs, say of size 500. I also need a smaller array of chars, say of size 100, which has nothing to do with the struct. To...
6
by: john | last post by:
Many times I have seen padding bits being mentioned here. What is the purpose of the padding bits?
3
by: vippstar | last post by:
Hey comp.lang.c I'm somewhat confused with bit padding. I tried searching the FAQ, but there isn't a search feature, so I used google and the search query: site:c-faq.com padding. I did not...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.