P6opaque can end up up serialising uninitialised memory. P6opaque's compose() needs to zero the freshly allocated repr_data->unbox_slots.
Not all the slots are used, but serialize_repr_data() will serialise all of them, and hence write out garbage to disk. This doesn't cause crashes, because the unused slots are never accessed, but it does conceal other problems. valgrind reports an awful lot of warnings, concealing real problems, and the generated bytecode files will not be byte-for-byte identical, preventing easy consistency checking. I don't think that there are that many places where this happens (but I haven't rigged the build to count them yet), so I don't think that it's worth adding to the C structures to remember how many slots are used, and updating the serialisation to serialise this. Particularly as the new variable length integers store 0 as 1 byte, it's likely that the overhead of serialising the count will be more than the saving from not serialising a few zeros. Patch attached. With this, core setting just produces 1 error from valgrind: ==11990== Memcheck, a memory error detector ==11990== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==11990== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==11990== Command: /home/nicholas/Sandpit/moar3/bin/moar --libpath=/home/nicholas/Sandpit/moar3/languages/nqp/lib perl6.moarvm --setting=NULL --optimize=3 --target=mbc --stagestats --output=CORE.setting.moarvm src/gen/m-CORE.setting ==11990== Stage start : 0.000 Stage parse : 1700.903 Stage syntaxcheck: 0.000 Stage ast : 0.001 Stage optimize : 110.726 Stage mast : 634.316 ==11990== Syscall param write(buf) points to uninitialised byte(s) ==11990== at 0x53FB650: __write_nocancel (in /lib64/libc-2.12.so) ==11990== by 0x5391D52: _IO_file_write@@GLIBC_2.2.5 (in /lib64/libc-2.12.so) ==11990== by 0x5391C19: _IO_file_xsputn@@GLIBC_2.2.5 (in /lib64/libc-2.12.so) ==11990== by 0x5387CCC: fwrite (in /lib64/libc-2.12.so) ==11990== by 0x4F55D8C: MVM_mast_to_file (driver.c:76) ==11990== by 0x4F0E87E: MVM_interp_run (interp.c:1263) ==11990== by 0x4F6434D: MVM_vm_run_file (moar.c:176) ==11990== by 0x400D3F: main (main.c:146) ==11990== Address 0x4a4cecc5 is 605,317 bytes inside a block of size 9,189,191 alloc'd ==11990== at 0x4C279EE: malloc (vg_replace_malloc.c:270) ==11990== by 0x4F552A5: form_bytecode_output (compiler.c:1152) ==11990== by 0x4F5591F: MVM_mast_compile (compiler.c:1315) ==11990== by 0x4F55D40: MVM_mast_to_file (driver.c:76) ==11990== by 0x4F0E87E: MVM_interp_run (interp.c:1263) ==11990== by 0x4F6434D: MVM_vm_run_file (moar.c:176) ==11990== by 0x400D3F: main (main.c:146) ==11990== Stage mbc : 30.383 ==11990== ==11990== HEAP SUMMARY: ==11990== in use at exit: 475,163,082 bytes in 2,210,555 blocks ==11990== total heap usage: 40,818,237 allocs, 38,607,682 frees, 12,409,867,903 bytes allocated ==11990== ==11990== LEAK SUMMARY: ==11990== definitely lost: 92,339,905 bytes in 1,564,719 blocks ==11990== indirectly lost: 53,682,608 bytes in 619,375 blocks ==11990== possibly lost: 12,354,562 bytes in 1,106 blocks ==11990== still reachable: 316,786,007 bytes in 25,355 blocks ==11990== suppressed: 0 bytes in 0 blocks ==11990== Rerun with --leak-check=full to see details of leaked memory ==11990== ==11990== For counts of detected and suppressed errors, rerun with: -v ==11990== Use --track-origins=yes to see where uninitialised values come from ==11990== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 9 from 9) I'm not sure how to find that one. Nicholas Clark
>From 9717c39e5e74cfe145e2210342e63f183478fa14 Mon Sep 17 00:00:00 2001 From: Nicholas Clark <n...@ccl4.org> Date: Mon, 27 Jan 2014 22:20:54 +0100 Subject: [PATCH] In P6opaque's compose(), zero the freshly allocated repr_data->unbox_slots. Not all the slots are used, but serialize_repr_data() will serialise all of them, and hence write out garbage to disk. This doesn't cause crashes, because the unuused slots are never accessed, but it does conceal other problems. valgrind reports an awful lot of warnings, concealing real problems, and the generated bytecode files will not be byte-for-byte identical, preventing easy consistency checking. --- src/6model/reprs/P6opaque.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/6model/reprs/P6opaque.c b/src/6model/reprs/P6opaque.c index e439ccb..4edbcf1 100644 --- a/src/6model/reprs/P6opaque.c +++ b/src/6model/reprs/P6opaque.c @@ -769,7 +769,7 @@ static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *info_hash) { /* Also list in the by-repr unbox list. */ if (repr_data->unbox_slots == NULL) - repr_data->unbox_slots = (MVMP6opaqueBoxedTypeMap *)malloc(total_attrs * sizeof(MVMP6opaqueBoxedTypeMap)); + repr_data->unbox_slots = (MVMP6opaqueBoxedTypeMap *)calloc(total_attrs, sizeof(MVMP6opaqueBoxedTypeMap)); repr_data->unbox_slots[cur_unbox_slot].repr_id = REPR(type)->ID; repr_data->unbox_slots[cur_unbox_slot].slot = cur_slot; cur_unbox_slot++; -- 1.7.1