Last active
April 19, 2021 17:33
-
-
Save silentbicycle/ee6982cf1f4d21e090a1768a0bf2ce96 to your computer and use it in GitHub Desktop.
uninitialized memory caused by struct padding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ cat space_padness.c | |
/* | |
* Copyright (c) 2016 Scott Vokes <vokes.s@gmail.com> | |
* | |
* Permission to use, copy, modify, and/or distribute this software for any | |
* purpose with or without fee is hereby granted, provided that the above | |
* copyright notice and this permission notice appear in all copies. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
*/ | |
/* Example of uninitialized memory due to struct padding. */ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdbool.h> | |
#include <string.h> | |
#include <assert.h> | |
struct thing { | |
uint32_t thing_1; | |
uint32_t thing_2; | |
uint32_t thing_3; | |
uint8_t two_more_bytes[2]; | |
// Uncommenting this padding field eliminates the issue. | |
// uint8_t padding[2]; | |
}; | |
static void init_t(struct thing *t) { | |
/* This designated initializer does _not_ zero the | |
* padding bytes; they're uninitialized memory. */ | |
*t = (struct thing) { | |
.thing_2 = 0xfa1afe1, | |
}; | |
} | |
int main(int argc, char **argv) { | |
struct thing t; | |
// Even memsetting the structure here doesn't help. | |
memset(&t, 0, sizeof(t)); | |
init_t(&t); | |
printf("sizeof(t): %zd\n", sizeof(t)); | |
uint8_t *raw = (uint8_t *)&t; | |
for (size_t i = 0; i < sizeof(t); i++) { | |
printf("%zd: 0x%02x\n", i, raw[i]); | |
} | |
uint32_t naive_hash = 0; | |
for (size_t i = 0; i < sizeof(t); i++) { | |
naive_hash += raw[i]; | |
} | |
printf("naive_hash: 0x%08x\n", naive_hash); | |
return 0; | |
} | |
$ clang -std=c99 -o space_padness -g space_padness.c && valgrind --track-origins=yes ./space_padness | |
==63611== Memcheck, a memory error detector | |
==63611== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. | |
==63611== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info | |
==63611== Command: ./space_padness | |
==63611== | |
sizeof(t): 16 | |
0: 0x00 | |
1: 0x00 | |
2: 0x00 | |
3: 0x00 | |
4: 0xe1 | |
5: 0xaf | |
6: 0xa1 | |
7: 0x0f | |
8: 0x00 | |
9: 0x00 | |
10: 0x00 | |
11: 0x00 | |
12: 0x00 | |
13: 0x00 | |
==63611== Conditional jump or move depends on uninitialised value(s) | |
==63611== at 0x1001D796B: __vfprintf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001FF7FE: __v2printf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001FFAD0: __xvprintf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001D59C1: vfprintf_l (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001D3827: printf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x100000E4E: main (space_padness.c:56) | |
==63611== Uninitialised value was created by a stack allocation | |
==63611== at 0x100000ED0: init_t (space_padness.c:37) | |
==63611== | |
==63611== Use of uninitialised value of size 8 | |
==63611== at 0x1001DA3BD: __ultoa (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001D79AE: __vfprintf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001FF7FE: __v2printf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001FFAD0: __xvprintf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001D59C1: vfprintf_l (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001D3827: printf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x100000E4E: main (space_padness.c:56) | |
==63611== Uninitialised value was created by a stack allocation | |
==63611== at 0x100000ED0: init_t (space_padness.c:37) | |
==63611== | |
==63611== Conditional jump or move depends on uninitialised value(s) | |
==63611== at 0x1001DA3CB: __ultoa (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001D79AE: __vfprintf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001FF7FE: __v2printf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001FFAD0: __xvprintf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001D59C1: vfprintf_l (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x1001D3827: printf (in /usr/lib/system/libsystem_c.dylib) | |
==63611== by 0x100000E4E: main (space_padness.c:56) | |
==63611== Uninitialised value was created by a stack allocation | |
==63611== at 0x100000ED0: init_t (space_padness.c:37) | |
==63611== | |
14: 0x00 | |
15: 0x00 | |
naive_hash: 0x00000240 | |
==63611== | |
==63611== HEAP SUMMARY: | |
==63611== in use at exit: 39,037 bytes in 417 blocks | |
==63611== total heap usage: 512 allocs, 95 frees, 45,877 bytes allocated | |
==63611== | |
==63611== LEAK SUMMARY: | |
==63611== definitely lost: 0 bytes in 0 blocks | |
==63611== indirectly lost: 0 bytes in 0 blocks | |
==63611== possibly lost: 0 bytes in 0 blocks | |
==63611== still reachable: 0 bytes in 0 blocks | |
==63611== suppressed: 39,037 bytes in 417 blocks | |
==63611== | |
==63611== For counts of detected and suppressed errors, rerun with: -v | |
==63611== ERROR SUMMARY: 12 errors from 3 contexts (suppressed: 0 from 0) | |
$ clang --version | |
Apple LLVM version 7.0.0 (clang-700.1.76) | |
Target: x86_64-apple-darwin14.5.0 | |
Thread model: posix | |
// The above code also triggered valgrind warnings with: | |
$ clang --version | |
Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0) | |
Target: x86_64-pc-linux-gnu | |
Thread model: posix | |
// but not | |
$ gcc --version | |
gcc (Debian 4.9.2-10) 4.9.2 | |
Copyright (C) 2014 Free Software Foundation, Inc. | |
This is free software; see the source for copying conditions. There is NO | |
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment