From: Shelikhoo <xiaokangwang@outlook.com>
Date: Sun, 5 Dec 2021 19:15:38 +0000
Subject: Fix DoS attack vulnerability in CommandSwitchAccountFactory

(cherry picked from commit c1af2bfd7aa59a4482aa7f6ec4b9208c1d350b5c)

Closes: #1010377
---
 proxy/vmess/encoding/commands.go      |  2 +-
 proxy/vmess/encoding/commands_test.go | 21 +++++++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/proxy/vmess/encoding/commands.go b/proxy/vmess/encoding/commands.go
index 4b0bc44..0d0d6c9 100644
--- a/proxy/vmess/encoding/commands.go
+++ b/proxy/vmess/encoding/commands.go
@@ -140,7 +140,7 @@ func (f *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error
 	}
 	cmd.Level = uint32(data[levelStart])
 	timeStart := levelStart + 1
-	if len(data) < timeStart {
+	if len(data) < timeStart+1 {
 		return nil, newError("insufficient length.")
 	}
 	cmd.ValidMin = data[timeStart]
diff --git a/proxy/vmess/encoding/commands_test.go b/proxy/vmess/encoding/commands_test.go
index a283352..db122c8 100644
--- a/proxy/vmess/encoding/commands_test.go
+++ b/proxy/vmess/encoding/commands_test.go
@@ -1,6 +1,7 @@
 package encoding_test
 
 import (
+	"github.com/stretchr/testify/assert"
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
@@ -35,3 +36,23 @@ func TestSwitchAccount(t *testing.T) {
 		t.Error(r)
 	}
 }
+
+func TestSwitchAccountBugOffByOne(t *testing.T) {
+	sa := &protocol.CommandSwitchAccount{
+		Port:     1234,
+		ID:       uuid.New(),
+		AlterIds: 1024,
+		Level:    128,
+		ValidMin: 16,
+	}
+
+	buffer := buf.New()
+	csaf := CommandSwitchAccountFactory{}
+	common.Must(csaf.Marshal(sa, buffer))
+
+	Payload := buffer.Bytes()
+
+	cmd, err := csaf.Unmarshal(Payload[:len(Payload)-1])
+	assert.Error(t, err)
+	assert.Nil(t, cmd)
+}
