Live data from Hacker News

Stop Memsetting Structures

anmolsarma.in

231–240 of 277 posts

Re: Stop Memsetting Structures

#231
post #229

Earlier quoted context omitted.

you can write your own memset that bypasses all of that. Its just 2 lines of code.

I don't trust any memset at all. Literally every single memset I looked at was either broken, too slow or insecure. Mostly the wellknown glibc, freebsd, msvcrt and compiler implementations.

That's quite a bold claim. Care to explain further?

Re: Stop Memsetting Structures

#232

Earlier quoted context omitted.

> No one in this sub-thread has mentioned (or implied) any "fix". You appear to be putting words in my mouth. I'm talking about the comments hermitdev was replying to that were treating memset as a 'fix'. And 'fix' is shorthand for the opposite of "open[ing] you up to all kinds of info leaks". I don't think that's putting words in anyone's mouth.

I guess we are misunderstanding each other's point. I just found hermitdev's comment to be misleading (despite being correct), but perhaps it's just my reading of it. To be fair though, memset() usually IS a fix. As mentioned by the kernel memzero_explicit() docs: > usually using memset is just fine (!) -- https://www.kernel.org/doc/htmldocs/kernel-api/API-memzero-e... A conforming C compiler can't just remove memset…

A conforming C compiler can remove a memset that has no side effects.

Re: Stop Memsetting Structures

#233
post #227

It is C99 code. It is worth noting that many C projects go for extreme portability. That's why C is used in the first place, and sometimes C99 is too much. I still sometimes work with compilers that barely support C89. That's for the aerospace industry BTW. There are even some libc that don't accept free(NULL). If you know the platform you are writing for is not ancient, that's fine but if you are writing portable co…

> There are even some libc that don't accept free(NULL).

That’s pretty much the completely opposite of portable, since it violates the C standard.

Re: Stop Memsetting Structures

#234

Earlier quoted context omitted.

I don't think memset is required to zero out any padding, because the effects of this are not observable.

The function memset gets the length of the area to overwrite, how is it to know where the padding is?

The compiler knows the layout of your structure and can choose to elide memset calls or replace them with equivalent code.

Re: Stop Memsetting Structures

#236
post #125

Earlier quoted context omitted.

That will never happen on current or future platforms, and is not a big concern. Or perhaps it'd be better to say that if it ever does happen on a future platform, then a few memset calls are going to be the least of your problems when porting legacy C code to that platform. However, what has bitten me is memsetting structures that I later turn into full-fledged classes in C++. Oops, there went the VMT. Designated in…

I do wish there was a compact way to tell a C++ class to zero init all pointer/numeric members to zero.

What's wrong with:

  T foo = {}

Re: Stop Memsetting Structures

#237
post #7

Another reason to not memset structures: In the code struct foo { void * bar; } baz; ... memset(&baz, 0, sizeof(struct foo)); assert(baz.bar == NULL); it's possible for the assertion to fail, since NULL it not guaranteed to be represented in memory by a zero bytes.

...are there any remaining architectures where NULL is not zero? The examples listed here are all historical: http://c-faq.com/null/machexamp.html

It does not matter if there are any architectures like that. Relying on that fact is still an undefined behavior. The compiler is allowed to produce any code it wants.

If you use memset to initialize structure with pointers with 0 and then test if the pointer are NULL, the compiler could assume that the pointer was not properly initialized and remove the if completely, or actually even remove the whole function.

Re: Stop Memsetting Structures

#238

Earlier quoted context omitted.

I guess we are misunderstanding each other's point. I just found hermitdev's comment to be misleading (despite being correct), but perhaps it's just my reading of it. To be fair though, memset() usually IS a fix. As mentioned by the kernel memzero_explicit() docs: > usually using memset is just fine (!) -- https://www.kernel.org/doc/htmldocs/kernel-api/API-memzero-e... A conforming C compiler can't just remove memset…

A conforming C compiler can remove a memset that has no side effects.

You mean it can remove a memset() that doesn't cause the observable behaviour to change?

For the sake of argument, can you show me some example code where it would be conforming to remove a memset() call? Preferably a realistic example and not a Google'd copypasta. Because it's all too easy to just regurgitate things you heard and think you understood, but no so easy to demonstrate it yourself.

Re: Stop Memsetting Structures

#239
post #12

Earlier quoted context omitted.

Sending structures that include padding or that you don’t know the exact layout of over the network is another thing you shouldn’t do, period. Code doing that may break with a compiler change or a compilation flag change on one end of the connection, even if you can guarantee both ends use the same CPU.

This kind of issue happens all the time with structs that a kernel, driver etc. expose to userspace: https://j00ru.vexillium.org/papers/2018/bochspwn_reloaded.pd... Not sending the structure over the network is insufficient, and rigorous memset is a clear solution to this problem. Also, C structure layout for a specific ABI is strictly determined; if that weren’t the case you couldn’t compile two C compilation units…

> Also, C structure layout for a specific ABI is strictly determined

That's true, but when sending stuff over the network you don't know if the receiver uses the same ABI.

Re: Stop Memsetting Structures

#240
post #75

Earlier quoted context omitted.

Nope, memset will often be “optimized” such that padding is not zeroed. It’s not because the compiler sees that padding isn’t observed, it’s because reading from padding is undefined. Because reading from padding is undefined the write (also undefined) by definition has no observable side effects. Memset_s is the only way to guarantee that padding is actually zeroed, well memset or bzero_s obviously. It’s critically…

are you sure that the padding is not zeroed by memset? [1] says that memset_s exists because it is not optimized away if it just clears a variable that will not be used after the call (unlike memset) On the other end: people who do this for security reasons say not to trust memset_s is 'an optional feature of c11 and not really portable' [2] [1] https://en.cppreference.com/w/c/string/byte/memset [2] https://www.crypt…

[deleted]
Post reply on HN