diff options
| author | Paul Eggert | 2022-12-17 23:11:55 -0800 |
|---|---|---|
| committer | Paul Eggert | 2022-12-18 00:24:13 -0800 |
| commit | bda755bf92b5fa0dfe25da173b30e1002e95b774 (patch) | |
| tree | a9aa1b5520a48c93a1702b39c1b2f22a32c46805 /lib/memset_explicit.c | |
| parent | 5a344d90c53d681ed98ab03ad3e218a3c6561108 (diff) | |
| download | emacs-bda755bf92b5fa0dfe25da173b30e1002e95b774.tar.gz emacs-bda755bf92b5fa0dfe25da173b30e1002e95b774.zip | |
Update from Gnulib by running admin/merge-gnulib
Diffstat (limited to 'lib/memset_explicit.c')
| -rw-r--r-- | lib/memset_explicit.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/lib/memset_explicit.c b/lib/memset_explicit.c new file mode 100644 index 00000000000..eabeb3ec2b8 --- /dev/null +++ b/lib/memset_explicit.c | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | /* Erase sensitive data from memory. | ||
| 2 | Copyright 2022 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU Lesser General Public License as | ||
| 6 | published by the Free Software Foundation; either version 2.1 of the | ||
| 7 | License, or (at your option) any later version. | ||
| 8 | |||
| 9 | This file is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU Lesser General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU Lesser General Public License | ||
| 15 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 16 | |||
| 17 | #include <config.h> | ||
| 18 | |||
| 19 | /* memset_s need this define */ | ||
| 20 | #if HAVE_MEMSET_S | ||
| 21 | # define __STDC_WANT_LIB_EXT1__ 1 | ||
| 22 | #endif | ||
| 23 | |||
| 24 | #include <string.h> | ||
| 25 | |||
| 26 | /* Set S's bytes to C, where S has LEN bytes. The compiler will not | ||
| 27 | optimize effects away, even if S is dead after the call. */ | ||
| 28 | void * | ||
| 29 | memset_explicit (void *s, int c, size_t len) | ||
| 30 | { | ||
| 31 | #if HAVE_EXPLICIT_MEMSET | ||
| 32 | return explicit_memset (s, c, len); | ||
| 33 | #elif HAVE_MEMSET_S | ||
| 34 | (void) memset_s (s, len, c, len); | ||
| 35 | return s; | ||
| 36 | #elif defined __GNUC__ && !defined __clang__ | ||
| 37 | memset (s, c, len); | ||
| 38 | /* Compiler barrier. */ | ||
| 39 | __asm__ volatile ("" ::: "memory"); | ||
| 40 | return s; | ||
| 41 | #elif defined __clang__ | ||
| 42 | memset (s, c, len); | ||
| 43 | /* Compiler barrier. */ | ||
| 44 | /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the | ||
| 45 | whole thing is dead and eliminates it. Use 'g' to work around this | ||
| 46 | problem. See <https://bugs.llvm.org/show_bug.cgi?id=15495#c11>. */ | ||
| 47 | __asm__ volatile ("" : : "g"(s) : "memory"); | ||
| 48 | return s; | ||
| 49 | #else | ||
| 50 | /* Invoke memset through a volatile function pointer. This defeats compiler | ||
| 51 | optimizations. */ | ||
| 52 | void * (* const volatile volatile_memset) (void *, int, size_t) = memset; | ||
| 53 | return volatile_memset (s, c, len); | ||
| 54 | #endif | ||
| 55 | } | ||