Skip to content

Instantly share code, notes, and snippets.

@silentbicycle
Last active April 19, 2021 17:33
Show Gist options
  • Save silentbicycle/ee6982cf1f4d21e090a1768a0bf2ce96 to your computer and use it in GitHub Desktop.
Save silentbicycle/ee6982cf1f4d21e090a1768a0bf2ce96 to your computer and use it in GitHub Desktop.
uninitialized memory caused by struct padding
$ 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