1

This is related to this question: is there is a way to memset a buffer after finished using it (for security for example) without it being optimized out?

Trying to cast the pointer to volatile pointer getting warning about sending volatile pointer to function that not expects volatile.

arye
  • 458
  • 3
  • 15
  • 1
    Are you looking for `memset_explicit()`? – Harith Apr 04 '23 at 09:47
  • If your standard library does not include `memset_explicit()` yet (it is in the draft C23 standard), you could use [Gnulib](https://www.gnu.org/software/gnulib/) to provide it. It implements it in various ways, depending on the compiler and library. – Ian Abbott Apr 04 '23 at 10:17
  • Thanks for the referenc to memset_explicit(), I wasn't aware to it. Unfortunately, my standard library not support it. – arye Apr 04 '23 at 10:52
  • 1
    Just overwrite the memory area yourself with zeroes using a loop and a volatile pointer. Assuming it is not performance critical and large, just writing byte by byte should be fine, but an optimized version could write most of it using 64 bit integer instead of char. – hyde Apr 04 '23 at 10:56

2 Answers2

5

The memset_explicit() function from the C23 draft standard does what you want, but might not be implemented in current versions of the C standard library. The GNU Gnulib (GNU Portability Library) includes a version of memset_explicit() that can be incorporated in a project's sources under the terms of the GNU Lesser General Public License. The initial import into a project assumes that the project uses Autoconf, so that could be a problem for projects that do not use Autoconf.

The Gnulib implementation of memset_explicit() uses conditional compilation to implement the function in various ways, such as calling memset_s() (if available), adding a memory barrier after a call to memset(), or if none of those can be used, calling memset() via a volatile function pointer. The use of a volatile function pointer involves defining and initializing a function pointer volatile_memset like this:

    void * (* const volatile volatile_memset) (void *, int, size_t) = memset;

Calls to memset() through the volatile_memset pointer will not be optimized away.

Ian Abbott
  • 15,083
  • 19
  • 33
  • Thanks, looks good. I suppose there is yet little down side here that the compiler can't optimize it in cases of short buffer to inline mem-setting. – arye Apr 04 '23 at 13:05
0

A fully portable version from C90 to C23 is to use a struct wrapper and then declare a volatile struct object:

typedef struct
{
  uint8_t buf [n];
} buf_t;


volatile buf_t buf = {0}; 
// equivalent to memset(buf, 0, sizeof buf) but can't be optimized out
...
static const buf_t final_settings = { ... }; 
// some values you wish the buffer to have in the end
...
buf = final_settings; 
// equivalent to memset/memcpy but can't be optimized out

This also dodges the quirk/flaw in C regarding "access of volatile object" vs "volatile lvalue access" (also fixed in C23).

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • What with the case that the buffer size not known in compile time? – arye Apr 04 '23 at 10:49
  • Can we replace buf = final_settings; by buf = (buf_t){0};? – arye Apr 04 '23 at 10:50
  • @arye "What with the case that the buffer size not known in compile time?" You didn't mention that as a requirement in the question. "Can we replace buf = final_settings; by buf = (buf_t){0};?" Yes. – Lundin Apr 04 '23 at 11:31
  • I upvoted the answer, but still waiting to see if someone will have more general and clean solution – arye Apr 04 '23 at 12:36