2f4f5e
diff -Naurp pcp-4.3.2.orig/qa/1820 pcp-4.3.2/qa/1820
2f4f5e
--- pcp-4.3.2.orig/qa/1820	1970-01-01 10:00:00.000000000 +1000
2f4f5e
+++ pcp-4.3.2/qa/1820	2020-11-04 11:14:36.844349843 +1100
2f4f5e
@@ -0,0 +1,40 @@
2f4f5e
+#!/bin/sh
2f4f5e
+# PCP QA Test No. 1820
2f4f5e
+# Exercise memory allocation bug in pcp-atopsar(1).
2f4f5e
+#
2f4f5e
+# Copyright (c) 2020 Red Hat.  All Rights Reserved.
2f4f5e
+#
2f4f5e
+
2f4f5e
+seq=`basename $0`
2f4f5e
+if [ $# -eq 0 ]
2f4f5e
+then
2f4f5e
+    echo "QA output created by $seq"
2f4f5e
+else
2f4f5e
+    echo "QA output created by $seq $*"
2f4f5e
+fi
2f4f5e
+
2f4f5e
+# get standard environment, filters and checks
2f4f5e
+. ./common.product
2f4f5e
+. ./common.filter
2f4f5e
+. ./common.check
2f4f5e
+
2f4f5e
+[ -f $PCP_BINADM_DIR/pcp-atopsar ] || _notrun "system monitoring tools not installed"
2f4f5e
+
2f4f5e
+_cleanup()
2f4f5e
+{
2f4f5e
+    cd $here
2f4f5e
+    $sudo rm -rf $tmp $tmp.*
2f4f5e
+}
2f4f5e
+
2f4f5e
+status=1	# failure is the default!
2f4f5e
+$sudo rm -rf $tmp $tmp.* $seq.full
2f4f5e
+trap "_cleanup; exit \$status" 0 1 2 3 15
2f4f5e
+
2f4f5e
+# real QA test starts here
2f4f5e
+export PCP_HOSTZONE=1
2f4f5e
+export PCP_ARCHIVE=$here/archives/pcp-atop-log
2f4f5e
+$PCP_BINADM_DIR/pcp-atopsar -x -R 5 2 10
2f4f5e
+
2f4f5e
+# success, all done
2f4f5e
+status=0
2f4f5e
+exit
2f4f5e
diff -Naurp pcp-4.3.2.orig/qa/1820.out pcp-4.3.2/qa/1820.out
2f4f5e
--- pcp-4.3.2.orig/qa/1820.out	1970-01-01 10:00:00.000000000 +1000
2f4f5e
+++ pcp-4.3.2/qa/1820.out	2020-11-04 11:14:36.844349843 +1100
2f4f5e
@@ -0,0 +1,14 @@
2f4f5e
+QA output created by 1820
2f4f5e
+
2f4f5e
+        2020/07/20
2f4f5e
+
2f4f5e
+-------------------------- analysis date: 2013/09/26 --------------------------
2f4f5e
+
2f4f5e
+16:14:15  cpu  %usr %nice %sys %irq %softirq  %steal %guest  %wait %idle  _cpu_
2f4f5e
+
2f4f5e
+16:14:19  cpu  %usr %nice %sys %irq %softirq  %steal %guest  %wait %idle  _cpu_
2f4f5e
+16:14:27  all    23     0    8    2        1       0      0      3   363
2f4f5e
+            0     5     3    1    4        4       3      3      4    75
2f4f5e
+            1    10     6    8    6        6       6      6      6    52
2f4f5e
+            2    11     6    8    6        6       6      6      6    51
2f4f5e
+            3    11     6    7    6        6       6      6      6    52
2f4f5e
diff -Naurp pcp-4.3.2.orig/qa/group pcp-4.3.2/qa/group
2f4f5e
--- pcp-4.3.2.orig/qa/group	2020-11-04 11:11:00.757951890 +1100
2f4f5e
+++ pcp-4.3.2/qa/group	2020-11-04 11:14:57.290103639 +1100
2f4f5e
@@ -1680,4 +1680,5 @@ BAD
2f4f5e
 1622 selinux local
2f4f5e
 1644 pmda.perfevent local
2f4f5e
 1671 multi-archive archive libpcp pmlogextract pmlogcheck pmdumplog local
2f4f5e
+1820 atop local
2f4f5e
 4751 libpcp threads valgrind local pcp python
2f4f5e
diff -Naurp pcp-4.3.2.orig/src/pcp/atop/deviate.c pcp-4.3.2/src/pcp/atop/deviate.c
2f4f5e
--- pcp-4.3.2.orig/src/pcp/atop/deviate.c	2020-11-04 11:11:00.762951830 +1100
2f4f5e
+++ pcp-4.3.2/src/pcp/atop/deviate.c	2020-11-04 11:14:36.846349819 +1100
2f4f5e
@@ -7,7 +7,7 @@
2f4f5e
 ** This source-file contains functions to calculate the differences for
2f4f5e
 ** the system-level and process-level counters since the previous sample.
2f4f5e
 **
2f4f5e
-** Copyright (C) 2015,2017,2019 Red Hat.
2f4f5e
+** Copyright (C) 2015,2017,2019-2020 Red Hat.
2f4f5e
 ** Copyright (C) 2000-2010 Gerlof Langeveld
2f4f5e
 **
2f4f5e
 ** This program is free software; you can redistribute it and/or modify it
2f4f5e
@@ -1220,6 +1220,7 @@ deviatsyst(struct sstat *cur, struct sst
2f4f5e
                                    pre->nfs.nfsmounts.nfsmnt[j].pagesmwrite);
2f4f5e
 	}
2f4f5e
 
2f4f5e
+	dev->nfs.nfsmounts.nfsmnt[i].mountdev[0] = '\0';
2f4f5e
 	dev->nfs.nfsmounts.nrmounts = cur->nfs.nfsmounts.nrmounts;
2f4f5e
 
2f4f5e
 	/*
2f4f5e
@@ -1227,7 +1228,7 @@ deviatsyst(struct sstat *cur, struct sst
2f4f5e
 	*/
2f4f5e
 	if (cur->cfs.nrcontainer != dev->cfs.nrcontainer)
2f4f5e
 	{
2f4f5e
-		size = (cur->cfs.nrcontainer + 1) * sizeof(struct percontainer);
2f4f5e
+		size = cur->cfs.nrcontainer * sizeof(struct percontainer);
2f4f5e
 		dev->cfs.cont = (struct percontainer *)realloc(dev->cfs.cont, size);
2f4f5e
 		ptrverify(dev->cfs.cont, "deviatsyst cont [%ld]\n", (long)size);
2f4f5e
 	}
2f4f5e
@@ -1283,6 +1284,12 @@ deviatsyst(struct sstat *cur, struct sst
2f4f5e
 	** application-specific counters
2f4f5e
 	** calculate deviations for GPUs
2f4f5e
 	*/
2f4f5e
+	if (cur->gpu.nrgpus != dev->gpu.nrgpus)
2f4f5e
+	{
2f4f5e
+		size = cur->gpu.nrgpus * sizeof(struct pergpu);
2f4f5e
+		dev->gpu.gpu = (struct pergpu *)realloc(dev->gpu.gpu, size);
2f4f5e
+		ptrverify(dev->gpu.gpu, "deviatsyst gpu [%ld]\n", (long)size);
2f4f5e
+	}
2f4f5e
 	for (i=0; i < cur->gpu.nrgpus; i++)
2f4f5e
 	{
2f4f5e
 	    dev->gpu.gpu[i].gpunr      = i;
2f4f5e
@@ -1325,6 +1332,12 @@ deviatsyst(struct sstat *cur, struct sst
2f4f5e
 	/*
2f4f5e
 	** calculate deviations for InfiniBand
2f4f5e
 	*/
2f4f5e
+	if (cur->ifb.nrports != dev->ifb.nrports)
2f4f5e
+	{
2f4f5e
+		size = (cur->ifb.nrports + 1) * sizeof(struct perifb);
2f4f5e
+		dev->ifb.ifb = (struct perifb *)realloc(dev->ifb.ifb, size);
2f4f5e
+		ptrverify(dev->ifb.ifb, "deviatsyst ifb [%ld]\n", (long)size);
2f4f5e
+	}
2f4f5e
 	for (i=0; i < cur->ifb.nrports; i++)
2f4f5e
 	{
2f4f5e
 		strcpy(dev->ifb.ifb[i].ibname, cur->ifb.ifb[i].ibname);
2f4f5e
@@ -1343,6 +1356,7 @@ deviatsyst(struct sstat *cur, struct sst
2f4f5e
 		                         pre->ifb.ifb[i].sndp;
2f4f5e
 	}
2f4f5e
 
2f4f5e
+	dev->ifb.ifb[i].ibname[0] = '\0';
2f4f5e
 	dev->ifb.nrports = cur->ifb.nrports;
2f4f5e
 
2f4f5e
 	/*
2f4f5e
@@ -1374,6 +1388,7 @@ totalsyst(char category, struct sstat *n
2f4f5e
 {
2f4f5e
 	register int	i;
2f4f5e
 	count_t		*ctot, *cnew;
2f4f5e
+	size_t		size;
2f4f5e
 
2f4f5e
 	switch (category)
2f4f5e
 	{
2f4f5e
@@ -1393,6 +1408,13 @@ totalsyst(char category, struct sstat *n
2f4f5e
 		tot->cpu.all.steal += new->cpu.all.steal;
2f4f5e
 		tot->cpu.all.guest += new->cpu.all.guest;
2f4f5e
 
2f4f5e
+		if (tot->cpu.nrcpu < new->cpu.nrcpu || !tot->cpu.cpu)
2f4f5e
+		{
2f4f5e
+		    size = new->cpu.nrcpu * sizeof(struct percpu);
2f4f5e
+		    tot->cpu.cpu = realloc(tot->cpu.cpu, size);
2f4f5e
+		    ptrverify(tot->cpu.cpu, "totalsyst cpus [%ld]", (long)size);
2f4f5e
+		}
2f4f5e
+
2f4f5e
 		if (new->cpu.nrcpu == 1)
2f4f5e
 		{
2f4f5e
 			tot->cpu.cpu[0] = tot->cpu.all;
2f4f5e
@@ -1537,6 +1559,13 @@ totalsyst(char category, struct sstat *n
2f4f5e
 		tot->net.tcp.MaxConn      = new->net.tcp.MaxConn;
2f4f5e
 		tot->net.tcp.CurrEstab    = new->net.tcp.CurrEstab;
2f4f5e
 	
2f4f5e
+		if (tot->intf.nrintf < new->intf.nrintf || !tot->intf.intf)
2f4f5e
+		{
2f4f5e
+		    size = (new->intf.nrintf + 1) * sizeof(struct perintf);
2f4f5e
+		    tot->intf.intf = realloc(tot->intf.intf, size);
2f4f5e
+		    ptrverify(tot->intf.intf, "totalsyst intfs [%ld]", (long)size);
2f4f5e
+		}
2f4f5e
+
2f4f5e
 		for (i=0; new->intf.intf[i].name[0]; i++)
2f4f5e
 		{
2f4f5e
 			/*
2f4f5e
@@ -1603,6 +1632,13 @@ totalsyst(char category, struct sstat *n
2f4f5e
 		break;
2f4f5e
 
2f4f5e
 	   case 'd':	/* accumulate disk-related counters */
2f4f5e
+		if (tot->dsk.ndsk < new->dsk.ndsk || !tot->dsk.dsk)
2f4f5e
+		{
2f4f5e
+		    size = (new->dsk.ndsk + 1) * sizeof(struct perdsk);
2f4f5e
+		    tot->dsk.dsk = realloc(tot->dsk.dsk, size);
2f4f5e
+		    ptrverify(tot->dsk.dsk, "totalsyst disks [%ld]", (long)size);
2f4f5e
+		}
2f4f5e
+
2f4f5e
 		for (i=0; new->dsk.dsk[i].name[0]; i++)
2f4f5e
 		{
2f4f5e
 			strcpy(tot->dsk.dsk[i].name, new->dsk.dsk[i].name);
2f4f5e
@@ -1618,6 +1654,13 @@ totalsyst(char category, struct sstat *n
2f4f5e
 		tot->dsk.dsk[i].name[0] = '\0';
2f4f5e
 		tot->dsk.ndsk = i;
2f4f5e
 
2f4f5e
+		if (tot->dsk.nlvm < new->dsk.nlvm || !tot->dsk.lvm)
2f4f5e
+		{
2f4f5e
+		    size = (new->dsk.nlvm + 1) * sizeof(struct perdsk);
2f4f5e
+		    tot->dsk.lvm = realloc(tot->dsk.lvm, size);
2f4f5e
+		    ptrverify(tot->dsk.lvm, "totalsyst LVs [%ld]", (long)size);
2f4f5e
+		}
2f4f5e
+
2f4f5e
 		for (i=0; new->dsk.lvm[i].name[0]; i++)
2f4f5e
 		{
2f4f5e
 			strcpy(tot->dsk.lvm[i].name, new->dsk.lvm[i].name);
2f4f5e
@@ -1633,6 +1676,13 @@ totalsyst(char category, struct sstat *n
2f4f5e
 		tot->dsk.lvm[i].name[0] = '\0';
2f4f5e
 		tot->dsk.nlvm = i;
2f4f5e
 
2f4f5e
+		if (tot->dsk.nmdd < new->dsk.nmdd || !tot->dsk.mdd)
2f4f5e
+		{
2f4f5e
+		    size = (new->dsk.nmdd + 1) * sizeof(struct perdsk);
2f4f5e
+		    tot->dsk.mdd = realloc(tot->dsk.mdd, size);
2f4f5e
+		    ptrverify(tot->dsk.mdd, "totalsyst MDs [%ld]", (long)size);
2f4f5e
+		}
2f4f5e
+
2f4f5e
 		for (i=0; new->dsk.mdd[i].name[0]; i++)
2f4f5e
 		{
2f4f5e
 			strcpy(tot->dsk.mdd[i].name, new->dsk.mdd[i].name);