aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuillaume Ballet <gballet@gmail.com>2018-03-27 23:26:08 +0800
committerGitHub <noreply@github.com>2018-03-27 23:26:08 +0800
commit80449719bd664bb0ed9c599765f6313f9b8a8303 (patch)
tree3294e5add82a09386532d97f156dc390431348a5
parent45bd4feddeadfbde5d1e560797155aacb0abbadf (diff)
downloaddexon-80449719bd664bb0ed9c599765f6313f9b8a8303.tar.gz
dexon-80449719bd664bb0ed9c599765f6313f9b8a8303.tar.zst
dexon-80449719bd664bb0ed9c599765f6313f9b8a8303.zip
whisper: fix issue in topic list copy (#16381)
- Fixes #16271. What was appeneded was a pointer to an object that changes during the iteration. - The topic is allocated as a 4-byte array, fill partial topics with 0s. Partial topics are currently disabled, but would crash as they rely on the presence of byte number 3.
-rw-r--r--whisper/whisperv6/api.go7
-rw-r--r--whisper/whisperv6/api_test.go78
2 files changed, 82 insertions, 3 deletions
diff --git a/whisper/whisperv6/api.go b/whisper/whisperv6/api.go
index 96e2b17e7..3f3a082af 100644
--- a/whisper/whisperv6/api.go
+++ b/whisper/whisperv6/api.go
@@ -558,9 +558,10 @@ func (api *PublicWhisperAPI) NewMessageFilter(req Criteria) (string, error) {
}
if len(req.Topics) > 0 {
- topics = make([][]byte, 0, len(req.Topics))
- for _, topic := range req.Topics {
- topics = append(topics, topic[:])
+ topics = make([][]byte, len(req.Topics))
+ for i, topic := range req.Topics {
+ topics[i] = make([]byte, TopicLength)
+ copy(topics[i], topic[:])
}
}
diff --git a/whisper/whisperv6/api_test.go b/whisper/whisperv6/api_test.go
new file mode 100644
index 000000000..004a41c94
--- /dev/null
+++ b/whisper/whisperv6/api_test.go
@@ -0,0 +1,78 @@
+// Copyright 2018 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package whisperv6
+
+import (
+ "bytes"
+ "crypto/ecdsa"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ set "gopkg.in/fatih/set.v0"
+)
+
+func TestMultipleTopicCopyInNewMessageFilter(t *testing.T) {
+ w := &Whisper{
+ privateKeys: make(map[string]*ecdsa.PrivateKey),
+ symKeys: make(map[string][]byte),
+ envelopes: make(map[common.Hash]*Envelope),
+ expirations: make(map[uint32]*set.SetNonTS),
+ peers: make(map[*Peer]struct{}),
+ messageQueue: make(chan *Envelope, messageQueueLimit),
+ p2pMsgQueue: make(chan *Envelope, messageQueueLimit),
+ quit: make(chan struct{}),
+ syncAllowance: DefaultSyncAllowance,
+ }
+ w.filters = NewFilters(w)
+
+ keyID, err := w.GenerateSymKey()
+ if err != nil {
+ t.Fatalf("Error generating symmetric key: %v", err)
+ }
+ api := PublicWhisperAPI{
+ w: w,
+ lastUsed: make(map[string]time.Time),
+ }
+
+ t1 := [4]byte{0xde, 0xea, 0xbe, 0xef}
+ t2 := [4]byte{0xca, 0xfe, 0xde, 0xca}
+
+ crit := Criteria{
+ SymKeyID: keyID,
+ Topics: []TopicType{TopicType(t1), TopicType(t2)},
+ }
+
+ _, err = api.NewMessageFilter(crit)
+ if err != nil {
+ t.Fatalf("Error creating the filter: %v", err)
+ }
+
+ found := false
+ candidates := w.filters.getWatchersByTopic(TopicType(t1))
+ for _, f := range candidates {
+ if len(f.Topics) == 2 {
+ if bytes.Equal(f.Topics[0], t1[:]) && bytes.Equal(f.Topics[1], t2[:]) {
+ found = true
+ }
+ }
+ }
+
+ if !found {
+ t.Fatalf("Could not find filter with both topics")
+ }
+}