From: Shengjing Zhu <zhsj@debian.org>
Date: Thu, 23 Sep 2021 23:12:05 +0800
Subject: Replace bitset with std math/big

Origin: backport, https://github.com/opencontainers/selinux/commit/4640bff
---
 go-selinux/selinux_linux.go | 68 ++++++++++++++++++++++-----------------------
 go.mod                      |  5 +---
 go.sum                      |  4 ---
 3 files changed, 34 insertions(+), 43 deletions(-)

diff --git a/go-selinux/selinux_linux.go b/go-selinux/selinux_linux.go
index 295b2bc..b045843 100644
--- a/go-selinux/selinux_linux.go
+++ b/go-selinux/selinux_linux.go
@@ -9,6 +9,7 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
+	"math/big"
 	"os"
 	"path"
 	"path/filepath"
@@ -16,7 +17,6 @@ import (
 	"strings"
 	"sync"
 
-	"github.com/bits-and-blooms/bitset"
 	"golang.org/x/sys/unix"
 )
 
@@ -44,7 +44,7 @@ type selinuxState struct {
 
 type level struct {
 	sens uint
-	cats *bitset.BitSet
+	cats *big.Int
 }
 
 type mlsRange struct {
@@ -455,8 +455,8 @@ func computeCreateContext(source string, target string, class string) (string, e
 }
 
 // catsToBitset stores categories in a bitset.
-func catsToBitset(cats string) (*bitset.BitSet, error) {
-	bitset := &bitset.BitSet{}
+func catsToBitset(cats string) (*big.Int, error) {
+	bitset := new(big.Int)
 
 	catlist := strings.Split(cats, ",")
 	for _, r := range catlist {
@@ -471,14 +471,14 @@ func catsToBitset(cats string) (*bitset.BitSet, error) {
 				return nil, err
 			}
 			for i := catstart; i <= catend; i++ {
-				bitset.Set(i)
+				bitset.SetBit(bitset, int(i), 1)
 			}
 		} else {
 			cat, err := parseLevelItem(ranges[0], category)
 			if err != nil {
 				return nil, err
 			}
-			bitset.Set(cat)
+			bitset.SetBit(bitset, int(cat), 1)
 		}
 	}
 
@@ -548,37 +548,30 @@ func rangeStrToMLSRange(rangeStr string) (*mlsRange, error) {
 
 // bitsetToStr takes a category bitset and returns it in the
 // canonical selinux syntax
-func bitsetToStr(c *bitset.BitSet) string {
+func bitsetToStr(c *big.Int) string {
 	var str string
-	i, e := c.NextSet(0)
-	len := 0
-	for e {
-		if len == 0 {
+
+	length := 0
+	for i := int(c.TrailingZeroBits()); i < c.BitLen(); i++ {
+		if c.Bit(i) == 0 {
+			continue
+		}
+		if length == 0 {
 			if str != "" {
 				str += ","
 			}
-			str += "c" + strconv.Itoa(int(i))
-		}
-
-		next, e := c.NextSet(i + 1)
-		if e {
-			// consecutive cats
-			if next == i+1 {
-				len++
-				i = next
-				continue
-			}
+			str += "c" + strconv.Itoa(i)
 		}
-		if len == 1 {
-			str += ",c" + strconv.Itoa(int(i))
-		} else if len > 1 {
-			str += ".c" + strconv.Itoa(int(i))
+		if c.Bit(i+1) == 1 {
+			length++
+			continue
 		}
-		if !e {
-			break
+		if length == 1 {
+			str += ",c" + strconv.Itoa(i)
+		} else if length > 1 {
+			str += ".c" + strconv.Itoa(i)
 		}
-		len = 0
-		i = next
+		length = 0
 	}
 
 	return str
@@ -591,13 +584,16 @@ func (l1 *level) equal(l2 *level) bool {
 	if l1.sens != l2.sens {
 		return false
 	}
-	return l1.cats.Equal(l2.cats)
+	if l2.cats == nil || l1.cats == nil {
+		return l2.cats == l1.cats
+	}
+	return l1.cats.Cmp(l2.cats) == 0
 }
 
 // String returns an mlsRange as a string.
 func (m mlsRange) String() string {
 	low := "s" + strconv.Itoa(int(m.low.sens))
-	if m.low.cats != nil && m.low.cats.Count() > 0 {
+	if m.low.cats != nil && m.low.cats.BitLen() > 0 {
 		low += ":" + bitsetToStr(m.low.cats)
 	}
 
@@ -606,7 +602,7 @@ func (m mlsRange) String() string {
 	}
 
 	high := "s" + strconv.Itoa(int(m.high.sens))
-	if m.high.cats != nil && m.high.cats.Count() > 0 {
+	if m.high.cats != nil && m.high.cats.BitLen() > 0 {
 		high += ":" + bitsetToStr(m.high.cats)
 	}
 
@@ -656,10 +652,12 @@ func calculateGlbLub(sourceRange, targetRange string) (string, error) {
 
 	/* find the intersecting categories */
 	if s.low.cats != nil && t.low.cats != nil {
-		outrange.low.cats = s.low.cats.Intersection(t.low.cats)
+		outrange.low.cats = new(big.Int)
+		outrange.low.cats.And(s.low.cats, t.low.cats)
 	}
 	if s.high.cats != nil && t.high.cats != nil {
-		outrange.high.cats = s.high.cats.Intersection(t.high.cats)
+		outrange.high.cats = new(big.Int)
+		outrange.high.cats.And(s.high.cats, t.high.cats)
 	}
 
 	return outrange.String(), nil
diff --git a/go.mod b/go.mod
index 0988279..93ee78e 100644
--- a/go.mod
+++ b/go.mod
@@ -2,7 +2,4 @@ module github.com/opencontainers/selinux
 
 go 1.13
 
-require (
-	github.com/bits-and-blooms/bitset v1.2.0
-	golang.org/x/sys v0.0.0-20191115151921-52ab43148777
-)
+require golang.org/x/sys v0.0.0-20191115151921-52ab43148777
diff --git a/go.sum b/go.sum
index a852f8b..9a749d7 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,2 @@
-github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
-github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
-github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 golang.org/x/sys v0.0.0-20191115151921-52ab43148777 h1:wejkGHRTr38uaKRqECZlsCsJ1/TGxIyFbH32x5zUdu4=
 golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
