Repository: elliotchance/pie
Pull request #146 (2019-05-18 08:05:21)

Issue145: fix memory overlap in DropTop
see [issue145](https://github.com/elliotchance/pie/issues/145)

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/elliotchance/pie/146)
<!-- Reviewable:end -->


codecov-io: # [Codecov](https://codecov.io/gh/elliotchance/pie/pull/146?src=pr&el=h1) Report
> :exclamation: No coverage uploaded for pull request base (`master@d758bde`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference#section-missing-base-commit).
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/elliotchance/pie/pull/146/graphs/tree.svg?width=650&token=OvugwUQGM3&height=150&src=pr)](https://codecov.io/gh/elliotchance/pie/pull/146?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##             master   #146   +/-   ##
=======================================
  Coverage          ?   100%           
=======================================
  Files             ?      8           
  Lines             ?   1483           
  Branches          ?      0           
=======================================
  Hits              ?   1483           
  Misses            ?      0           
  Partials          ?      0
```


| [Impacted Files](https://codecov.io/gh/elliotchance/pie/pull/146?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pie/float64s\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/146/diff?src=pr&el=tree#diff-cGllL2Zsb2F0NjRzX3BpZS5nbw==) | `100% <100%> (ø)` | |
| [pie/strings\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/146/diff?src=pr&el=tree#diff-cGllL3N0cmluZ3NfcGllLmdv) | `100% <100%> (ø)` | |
| [pie/cars\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/146/diff?src=pr&el=tree#diff-cGllL2NhcnNfcGllLmdv) | `100% <100%> (ø)` | |
| [pie/carpointers\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/146/diff?src=pr&el=tree#diff-cGllL2NhcnBvaW50ZXJzX3BpZS5nbw==) | `100% <100%> (ø)` | |
| [pie/ints\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/146/diff?src=pr&el=tree#diff-cGllL2ludHNfcGllLmdv) | `100% <100%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/elliotchance/pie/pull/146?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/elliotchance/pie/pull/146?src=pr&el=footer). Last update [d758bde...aedd00f](https://codecov.io/gh/elliotchance/pie/pull/146?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/functions/drop_top.go b/functions/drop_top.go
index 94f6a37..dcdbc11 100644
--- a/functions/drop_top.go
+++ b/functions/drop_top.go
@@ -8,7 +8,10 @@ func (ss SliceType) DropTop(n int) (drop SliceType) {
 		return
 	}
 
-	drop = ss[n:]
+	// Copy ss, to make sure no memory is overlapping between input and
+	// output. See issue #145.
+	drop = make([]ElementType, len(ss)-n)
+	copy(drop, ss[n:])
 
 	return
 }
diff --git a/pie/carpointers_pie.go b/pie/carpointers_pie.go
index 2df30d0..ffd1880 100755
--- a/pie/carpointers_pie.go
+++ b/pie/carpointers_pie.go
@@ -127,7 +127,10 @@ func (ss carPointers) DropTop(n int) (drop carPointers) {
 		return
 	}
 
-	drop = ss[n:]
+	// Copy ss, to make sure no memory is overlapping between input and
+	// output. See issue #145.
+	drop = make([]*car, len(ss)-n)
+	copy(drop, ss[n:])
 
 	return
 }
diff --git a/pie/cars_pie.go b/pie/cars_pie.go
index 71bea5d..1e978b2 100755
--- a/pie/cars_pie.go
+++ b/pie/cars_pie.go
@@ -127,7 +127,10 @@ func (ss cars) DropTop(n int) (drop cars) {
 		return
 	}
 
-	drop = ss[n:]
+	// Copy ss, to make sure no memory is overlapping between input and
+	// output. See issue #145.
+	drop = make([]car, len(ss)-n)
+	copy(drop, ss[n:])
 
 	return
 }
diff --git a/pie/float64s_pie.go b/pie/float64s_pie.go
index c4e63d6..9e8b256 100755
--- a/pie/float64s_pie.go
+++ b/pie/float64s_pie.go
@@ -165,7 +165,10 @@ func (ss Float64s) DropTop(n int) (drop Float64s) {
 		return
 	}
 
-	drop = ss[n:]
+	// Copy ss, to make sure no memory is overlapping between input and
+	// output. See issue #145.
+	drop = make([]float64, len(ss)-n)
+	copy(drop, ss[n:])
 
 	return
 }
diff --git a/pie/ints_pie.go b/pie/ints_pie.go
index 24e2ebb..b8e55cf 100755
--- a/pie/ints_pie.go
+++ b/pie/ints_pie.go
@@ -165,7 +165,10 @@ func (ss Ints) DropTop(n int) (drop Ints) {
 		return
 	}
 
-	drop = ss[n:]
+	// Copy ss, to make sure no memory is overlapping between input and
+	// output. See issue #145.
+	drop = make([]int, len(ss)-n)
+	copy(drop, ss[n:])
 
 	return
 }
diff --git a/pie/strings_pie.go b/pie/strings_pie.go
index 687c5cc..a302a03 100755
--- a/pie/strings_pie.go
+++ b/pie/strings_pie.go
@@ -141,7 +141,10 @@ func (ss Strings) DropTop(n int) (drop Strings) {
 		return
 	}
 
-	drop = ss[n:]
+	// Copy ss, to make sure no memory is overlapping between input and
+	// output. See issue #145.
+	drop = make([]string, len(ss)-n)
+	copy(drop, ss[n:])
 
 	return
 }
diff --git a/template.go b/template.go
index 7098b9b..51346c9 100644
--- a/template.go
+++ b/template.go
@@ -183,7 +183,10 @@ func (ss SliceType) DropTop(n int) (drop SliceType) {
 		return
 	}
 
-	drop = ss[n:]
+	// Copy ss, to make sure no memory is overlapping between input and
+	// output. See issue #145.
+	drop = make([]ElementType, len(ss)-n)
+	copy(drop, ss[n:])
 
 	return
 }


Test patch:
diff --git a/pie/strings_test.go b/pie/strings_test.go
index c59a5e1..d3cdb04 100644
--- a/pie/strings_test.go
+++ b/pie/strings_test.go
@@ -1156,6 +1156,31 @@ func TestStrings_DropTop(t *testing.T) {
 	}
 }
 
+// Make sure that input and output of DropTop don't share the same memory.
+func TestDropTopNonDestructive(t *testing.T) {
+	abc := Strings{"A", "B", "C"}
+
+	abc1 := abc.DropTop(0)
+	abc1[0] = "a"
+
+	if x, expected := abc.Join(""), "ABC"; x != expected {
+		t.Errorf("Expected %q, got %q", expected, x)
+	}
+	if x, expected := abc1.Join(""), "aBC"; x != expected {
+		t.Errorf("Expected %q, got %q", expected, x)
+	}
+
+	bc := abc.DropTop(1)
+	bc[0] = "D"
+
+	if x, expected := abc.Join(""), "ABC"; x != expected {
+		t.Errorf("Expected %q, got %q", expected, x)
+	}
+	if x, expected := bc.Join(""), "DC"; x != expected {
+		t.Errorf("Expected %q, got %q", expected, x)
+	}
+}
+
 var stringsSubSliceTests = []struct {
 	ss       Strings
 	start    int