From 748ae95f4aa93e482552dc418cb1e0273ffe843a Mon Sep 17 00:00:00 2001 From: bluhm Date: Sun, 3 Sep 2023 00:48:54 +0000 Subject: [PATCH] Zero initialize Perl AV elements after unshift and resize. https://github.com/Perl/perl5/issues/21235 https://github.com/Perl/perl5/pull/21265 https://github.com/Perl/perl5/commit/9e298ab597b2c6fc0741749d7e29119e2d6cd628 Bug reported by Anton Borowka. Fix from upstream Perl. OK afresh1@ --- gnu/usr.bin/perl/av.c | 24 ++++++++++++++++++++---- gnu/usr.bin/perl/t/op/array.t | 6 +++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/gnu/usr.bin/perl/av.c b/gnu/usr.bin/perl/av.c index 090c5a93f4c..c5713458842 100644 --- a/gnu/usr.bin/perl/av.c +++ b/gnu/usr.bin/perl/av.c @@ -103,12 +103,19 @@ Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp, "panic: av_extend_guts() negative count (%" IVdf ")", (IV)key); if (key > *maxp) { - SSize_t ary_offset = *maxp + 1; - SSize_t to_null = 0; + SSize_t ary_offset = *maxp + 1; /* Start NULL initialization + * from this element */ + SSize_t to_null = 0; /* How many elements to Zero */ SSize_t newmax = 0; if (av && *allocp != *arrayp) { /* a shifted SV* array exists */ + + /* to_null will contain the number of elements currently + * shifted and about to be unshifted. If the array has not + * been shifted to the maximum possible extent, this will be + * a smaller number than (*maxp - AvFILLp(av)). */ to_null = *arrayp - *allocp; + *maxp += to_null; ary_offset = AvFILLp(av) + 1; @@ -116,6 +123,13 @@ Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp, if (key > *maxp - 10) { newmax = key + *maxp; + + /* Zero everything above AvFILLp(av), which could be more + * elements than have actually been shifted. If we don't + * do this, trailing elements at the end of the resized + * array may not be correctly initialized. */ + to_null = *maxp - AvFILLp(av); + goto resize; } } else if (*allocp) { /* a full SV* array exists */ @@ -167,7 +181,9 @@ Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp, #ifdef Perl_safesysmalloc_size resized: #endif - to_null += newmax - *maxp; + to_null += newmax - *maxp; /* Initialize all new elements + * (newmax - *maxp) in addition to + * any previously specified */ *maxp = newmax; /* See GH#18014 for discussion of when this might be needed: */ @@ -193,7 +209,7 @@ Perl_av_extend_guts(pTHX_ AV *av, SSize_t key, SSize_t *maxp, SV ***allocp, * don't get any special treatment here. * See https://github.com/Perl/perl5/pull/18690 for more detail */ ary_offset = 0; - to_null = *maxp+1; + to_null = *maxp+1; /* Initialize all new array elements */ goto zero; } diff --git a/gnu/usr.bin/perl/t/op/array.t b/gnu/usr.bin/perl/t/op/array.t index 188bedfecd0..ae2ac32be52 100644 --- a/gnu/usr.bin/perl/t/op/array.t +++ b/gnu/usr.bin/perl/t/op/array.t @@ -6,7 +6,7 @@ BEGIN { set_up_inc('.', '../lib'); } -plan (194); +plan (195); # # @foo, @bar, and @ary are also used from tie-stdarray after tie-ing them @@ -686,4 +686,8 @@ $#a = -1; $#a++; 'holes passed to sub do not lose their position (aelem, mg)'; } +# GH #21235 +fresh_perl_is('my @x;$x[0] = 1;shift @x;$x[22] = 1;$x[25] = 1;','', + {}, 'unshifting and growing an array initializes trailing elements'); + "We're included by lib/Tie/Array/std.t so we need to return something true"; -- 2.20.1