Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

memset_s(): What does the standard mean with this piece of text?

In C11, K.3.7.4.1 The memset_s function, I found this bit of rather confusing text:

Unlike memset, any call to the memset_s function shall be evaluated strictly according to the rules of the abstract machine as described in (5.1.2.3). That is, any call to the memset_s function shall assume that the memory indicated by s and n may be accessible in the future and thus must contain the values indicated by c.

This implies that memset is not (necessarily) "evaluated strictly according to the rules of the abstract machine". (The chapter referenced is 5.1.2.3 Program execution.)

I fail to understand the leeway the standard gives to memset that is explicitly ruled out here for memset_s, and what that would mean for an implementor of either function.

like image 457
DevSolar Avatar asked Jun 12 '19 15:06

DevSolar


People also ask

What does memset do in C?

The memset() function sets the first count bytes of dest to the value c . The value of c is converted to an unsigned character. The memset() function returns a pointer to dest .

Why does Bzero () is preferred compared to memset () in network programming?

Bzero is non-standard and portable while memset is. memset has the same features as bzero but more. With memset the setting of the bytes does not have to be zero. It can be any signed int.

Is memset optimized?

All zeroing operations that the pool allocator performs and many structure/array initializations that InitAll performs end up going through the memset function. Memset is one of the hottest functions on the operating system and is already quite optimized as a result.

What library is memset in?

C library function - memset() The C library function void *memset(void *str, int c, size_t n) copies the character c (an unsigned char) to the first n characters of the string pointed to, by the argument str.


1 Answers

Imagine you have read a password:

{
    char password[128];

    if (fgets(password, sizeof(password), stdin) != 0)
    {
        password[strcspn(password), "\n\r"]) = '\0';
        validate_password(password);
        memset(password, '\0', sizeof(password));
    }
}

You've carefully zapped the password so it can't be found accidentally.

Unfortunately, the compiler is allowed to omit that memset() call because password is not used again. The rule for memset_s() means that the call cannot be omitted; the password variable must be zeroed, regardless of optimization.

memset_s(password, sizeof(password), '\0', sizeof(password));

This is one of the few really useful features in Annex K. (We can debate the merits of having to repeat the size. However, in a more general case, the second size can be a variable, not a constant, and then the first size becomes a runtime protection against the variable being out of control.)

Note that this requirement is placed on the compiler rather than the library. The memset_s() function will behave correctly if it is called, just as memset() will behave correctly if it is called. The rule under discussion says that the compiler must call memset_s(), even though it may be able omit the call to memset() because the variable is never used again.

like image 190
Jonathan Leffler Avatar answered Sep 29 '22 23:09

Jonathan Leffler