Subject: | Use of uninitialized struct member |
This code in xs-src/pack.c:
enc_t enc;
enc.sv = sv_2mortal(newSV(INIT_SIZE));
enc.cur = SvPVX(enc.sv);
enc.end = SvEND(enc.sv);
SvPOK_only(enc.sv);
// setup configuration
dMY_CXT;
enc.prefer_int = MY_CXT.prefer_int; // back compat
if(SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV) {
HV* const hv = (HV*)SvRV(self);
SV** svp;
svp = hv_fetchs(hv, "prefer_integer", FALSE);
if(svp) {
enc.prefer_int = SvTRUE(*svp) ? true : false;
}
svp = hv_fetchs(hv, "canonical", FALSE);
if(svp) {
enc.canonical = SvTRUE(*svp) ? true : false;
}
}
has no else block to set enc.canonical to a default value.
A simple ‘one’-liner like this:
$ perl5.18.1 -Mblib -e 'use Data::MessagePack; $VAR1 = { "xxx" => undef, "zzz" => "hooo", "yyy" => "25c", "k_1" => undef, "k_2" => "b", "k_3" => "hooo" }; use Data::Dumper; ++$Data::Dumper::Useqq; warn Dumper +Data::MessagePack->pack($VAR1)'
sorts the keys, because enc.canonical happens to be true here.
Bleadperl (as of commit de935cc) does not sort the keys, because pp_entersub’s variables have grown slightly, shifting things around slightly in memory such that enc.canonical ends up being false.
This causes test failures with Data::Model, which expects canonical to be true by default. (See <https://rt.perl.org/rt3/Ticket/Display.html?id=119771>.)
The attached patch is one possible fix for this. If the intent is actually to have enc.canonical default to 0, then I can submit a patch for Data::Model’s tests, so it sets it to 1 explicitly. (In fact, I will probably do that anyway.)