LP1953044 Avoid ref to free'd array in Server child maintenance user/berick/lp1953044-loop-freed-value
authorBill Erickson <berickxx@gmail.com>
Mon, 25 Jul 2022 14:05:23 +0000 (10:05 -0400)
committerBill Erickson <berickxx@gmail.com>
Mon, 25 Jul 2022 14:05:27 +0000 (10:05 -0400)
The Server active_list array is replaced / rebuilt during child process
maintenance.  Because of this, referencing the array ref can lead to the
below error if child process maintance occurs via signal mid-loop.

server: died with error Use of freed value in iteration
at /usr/lib/x86_64-linux-gnu/perl/5.28/IO/Select.pm line 70.

Avoid requiring array dereferencing on a potentially freed value by
creating a local array containing the original contents of idle_list.

Additionally, sanity check the child objects to verify they are not in
the middle of getting cleaned up.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
src/perl/lib/OpenSRF/Server.pm

index 52c53d2..0078fbc 100644 (file)
@@ -422,7 +422,14 @@ sub check_status {
 
         # refresh the read_set handles in case we lost a child in the previous iteration
         my $read_set = IO::Select->new;
-        $read_set->add($_->{pipe_to_child}) for @{$self->{active_list}};
+
+        # Copy the array so there's no chance we try to reference a
+        # free'd array ref in the loop below as a result of child
+        # process maintenance.
+        my @active = @{$self->{active_list}};
+
+        $read_set->add($_->{pipe_to_child}) for
+            grep {$_ && $_->{pipe_to_child}} @active;
 
         if(my @handles = $read_set->can_read(($block) ? undef : 0)) {
             my $pid = '';