summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-store
diff options
context:
space:
mode:
authorLibravatar kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>2021-12-20 09:35:32 +0000
committerLibravatar GitHub <noreply@github.com>2021-12-20 10:35:32 +0100
commit635ad2a42f10a5b24f08021782b71b4cf8326e19 (patch)
tree3221d2c4526b5214c9a9b9d33343d48b2e9c9649 /vendor/codeberg.org/gruf/go-store
parentLog when listening (#350) (diff)
downloadgotosocial-635ad2a42f10a5b24f08021782b71b4cf8326e19.tar.xz
Update codeberg.org/gruf libraries and fix go-store issue (#347)
* update codeberg.org/gruf/ libraries Signed-off-by: kim <grufwub@gmail.com> * another update Signed-off-by: kim <grufwub@gmail.com>
Diffstat (limited to 'vendor/codeberg.org/gruf/go-store')
-rw-r--r--vendor/codeberg.org/gruf/go-store/kv/state.go63
-rw-r--r--vendor/codeberg.org/gruf/go-store/kv/store.go42
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/block.go8
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/disk.go8
-rw-r--r--vendor/codeberg.org/gruf/go-store/storage/memory.go42
-rw-r--r--vendor/codeberg.org/gruf/go-store/util/fs.go20
6 files changed, 104 insertions, 79 deletions
diff --git a/vendor/codeberg.org/gruf/go-store/kv/state.go b/vendor/codeberg.org/gruf/go-store/kv/state.go
index a8c1b9c82..20a3e951d 100644
--- a/vendor/codeberg.org/gruf/go-store/kv/state.go
+++ b/vendor/codeberg.org/gruf/go-store/kv/state.go
@@ -2,6 +2,7 @@ package kv
import (
"io"
+ "sync"
"codeberg.org/gruf/go-errors"
)
@@ -15,9 +16,14 @@ var ErrStateClosed = errors.New("store/kv: state closed")
// then the state has zero guarantees
type StateRO struct {
store *KVStore
+ mutex sync.RWMutex
}
func (st *StateRO) Get(key string) ([]byte, error) {
+ // Get state read lock
+ st.mutex.RLock()
+ defer st.mutex.RUnlock()
+
// Check not closed
if st.store == nil {
return nil, ErrStateClosed
@@ -28,6 +34,10 @@ func (st *StateRO) Get(key string) ([]byte, error) {
}
func (st *StateRO) GetStream(key string) (io.ReadCloser, error) {
+ // Get state read lock
+ st.mutex.RLock()
+ defer st.mutex.RUnlock()
+
// Check not closed
if st.store == nil {
return nil, ErrStateClosed
@@ -38,6 +48,10 @@ func (st *StateRO) GetStream(key string) (io.ReadCloser, error) {
}
func (st *StateRO) Has(key string) (bool, error) {
+ // Get state read lock
+ st.mutex.RLock()
+ defer st.mutex.RUnlock()
+
// Check not closed
if st.store == nil {
return false, ErrStateClosed
@@ -47,8 +61,16 @@ func (st *StateRO) Has(key string) (bool, error) {
return st.store.has(key)
}
-func (st *StateRO) close() {
- st.store = nil
+func (st *StateRO) Release() {
+ // Get state write lock
+ st.mutex.Lock()
+ defer st.mutex.Unlock()
+
+ // Release the store
+ if st.store != nil {
+ st.store.mutex.RUnlock()
+ st.store = nil
+ }
}
// StateRW provides a read-write window to the store. While this
@@ -58,9 +80,14 @@ func (st *StateRO) close() {
// then the state has zero guarantees
type StateRW struct {
store *KVStore
+ mutex sync.RWMutex
}
func (st *StateRW) Get(key string) ([]byte, error) {
+ // Get state read lock
+ st.mutex.RLock()
+ defer st.mutex.RUnlock()
+
// Check not closed
if st.store == nil {
return nil, ErrStateClosed
@@ -71,6 +98,10 @@ func (st *StateRW) Get(key string) ([]byte, error) {
}
func (st *StateRW) GetStream(key string) (io.ReadCloser, error) {
+ // Get state read lock
+ st.mutex.RLock()
+ defer st.mutex.RUnlock()
+
// Check not closed
if st.store == nil {
return nil, ErrStateClosed
@@ -81,6 +112,10 @@ func (st *StateRW) GetStream(key string) (io.ReadCloser, error) {
}
func (st *StateRW) Put(key string, value []byte) error {
+ // Get state read lock
+ st.mutex.RLock()
+ defer st.mutex.RUnlock()
+
// Check not closed
if st.store == nil {
return ErrStateClosed
@@ -91,6 +126,10 @@ func (st *StateRW) Put(key string, value []byte) error {
}
func (st *StateRW) PutStream(key string, r io.Reader) error {
+ // Get state read lock
+ st.mutex.RLock()
+ defer st.mutex.RUnlock()
+
// Check not closed
if st.store == nil {
return ErrStateClosed
@@ -101,6 +140,10 @@ func (st *StateRW) PutStream(key string, r io.Reader) error {
}
func (st *StateRW) Has(key string) (bool, error) {
+ // Get state read lock
+ st.mutex.RLock()
+ defer st.mutex.RUnlock()
+
// Check not closed
if st.store == nil {
return false, ErrStateClosed
@@ -111,6 +154,10 @@ func (st *StateRW) Has(key string) (bool, error) {
}
func (st *StateRW) Delete(key string) error {
+ // Get state read lock
+ st.mutex.RLock()
+ defer st.mutex.RUnlock()
+
// Check not closed
if st.store == nil {
return ErrStateClosed
@@ -120,6 +167,14 @@ func (st *StateRW) Delete(key string) error {
return st.store.delete(key)
}
-func (st *StateRW) close() {
- st.store = nil
+func (st *StateRW) Release() {
+ // Get state write lock
+ st.mutex.Lock()
+ defer st.mutex.Unlock()
+
+ // Release the store
+ if st.store != nil {
+ st.store.mutex.Unlock()
+ st.store = nil
+ }
}
diff --git a/vendor/codeberg.org/gruf/go-store/kv/store.go b/vendor/codeberg.org/gruf/go-store/kv/store.go
index 148e3f33d..34fe91987 100644
--- a/vendor/codeberg.org/gruf/go-store/kv/store.go
+++ b/vendor/codeberg.org/gruf/go-store/kv/store.go
@@ -212,32 +212,34 @@ func (st *KVStore) Iterator(matchFn func(string) bool) (*KVIterator, error) {
}, nil
}
-// Read provides a read-only window to the store, holding it in a read-locked state until
-// the supplied function returns
-func (st *KVStore) Read(do func(*StateRO)) {
- // Get store read lock
+// Read provides a read-only window to the store, holding it in a read-locked state until release
+func (st *KVStore) Read() *StateRO {
st.mutex.RLock()
- defer st.mutex.RUnlock()
+ return &StateRO{store: st}
+}
- // Create new store state (defer close)
- state := &StateRO{store: st}
- defer state.close()
+// ReadFn provides a read-only window to the store, holding it in a read-locked state until fn return.
+func (st *KVStore) ReadFn(fn func(*StateRO)) {
+ // Acquire read-only state
+ state := st.Read()
+ defer state.Release()
- // Pass state
- do(state)
+ // Pass to fn
+ fn(state)
}
-// Update provides a read-write window to the store, holding it in a read-write-locked state
-// until the supplied functions returns
-func (st *KVStore) Update(do func(*StateRW)) {
- // Get store lock
+// Update provides a read-write window to the store, holding it in a write-locked state until release
+func (st *KVStore) Update() *StateRW {
st.mutex.Lock()
- defer st.mutex.Unlock()
+ return &StateRW{store: st}
+}
- // Create new store state (defer close)
- state := &StateRW{store: st}
- defer state.close()
+// UpdateFn provides a read-write window to the store, holding it in a write-locked state until fn return.
+func (st *KVStore) UpdateFn(fn func(*StateRW)) {
+ // Acquire read-write state
+ state := st.Update()
+ defer state.Release()
- // Pass state
- do(state)
+ // Pass to fn
+ fn(state)
}
diff --git a/vendor/codeberg.org/gruf/go-store/storage/block.go b/vendor/codeberg.org/gruf/go-store/storage/block.go
index 112b67d80..9a8c4dc7d 100644
--- a/vendor/codeberg.org/gruf/go-store/storage/block.go
+++ b/vendor/codeberg.org/gruf/go-store/storage/block.go
@@ -585,8 +585,8 @@ func (st *BlockStorage) WalkKeys(opts WalkKeysOptions) error {
// nodePathForKey calculates the node file path for supplied key
func (st *BlockStorage) nodePathForKey(key string) (string, error) {
- // Path separators are illegal
- if strings.Contains(key, "/") {
+ // Path separators are illegal, as directory paths
+ if strings.Contains(key, "/") || key == "." || key == ".." {
return "", ErrInvalidKey
}
@@ -594,6 +594,10 @@ func (st *BlockStorage) nodePathForKey(key string) (string, error) {
pb := util.GetPathBuilder()
defer util.PutPathBuilder(pb)
+ // Append the nodepath to key
+ pb.AppendString(st.nodePath)
+ pb.AppendString(key)
+
// Return joined + cleaned node-path
return pb.Join(st.nodePath, key), nil
}
diff --git a/vendor/codeberg.org/gruf/go-store/storage/disk.go b/vendor/codeberg.org/gruf/go-store/storage/disk.go
index cbc365eed..060d56688 100644
--- a/vendor/codeberg.org/gruf/go-store/storage/disk.go
+++ b/vendor/codeberg.org/gruf/go-store/storage/disk.go
@@ -69,7 +69,6 @@ func getDiskConfig(cfg *DiskConfig) DiskConfig {
// DiskStorage is a Storage implementation that stores directly to a filesystem
type DiskStorage struct {
path string // path is the root path of this store
- dots int // dots is the "dotdot" count for the root store path
bufp pools.BufferPool // bufp is the buffer pool for this DiskStorage
config DiskConfig // cfg is the supplied configuration for this store
}
@@ -120,7 +119,6 @@ func OpenFile(path string, cfg *DiskConfig) (*DiskStorage, error) {
// Return new DiskStorage
return &DiskStorage{
path: path,
- dots: util.CountDotdots(path),
bufp: pools.NewBufferPool(config.WriteBufSize),
config: config,
}, nil
@@ -282,10 +280,10 @@ func (st *DiskStorage) filepath(key string) (string, error) {
pb.AppendString(st.path)
pb.AppendString(key)
- // If path is dir traversal, and traverses FURTHER
- // than store root, this is an error
- if util.CountDotdots(pb.StringPtr()) > st.dots {
+ // Check for dir traversal outside of root
+ if util.IsDirTraversal(st.path, pb.StringPtr()) {
return "", ErrInvalidKey
}
+
return pb.String(), nil
}
diff --git a/vendor/codeberg.org/gruf/go-store/storage/memory.go b/vendor/codeberg.org/gruf/go-store/storage/memory.go
index e30aef571..be60fa464 100644
--- a/vendor/codeberg.org/gruf/go-store/storage/memory.go
+++ b/vendor/codeberg.org/gruf/go-store/storage/memory.go
@@ -2,7 +2,6 @@ package storage
import (
"io"
- "sync"
"codeberg.org/gruf/go-bytes"
"codeberg.org/gruf/go-store/util"
@@ -12,14 +11,12 @@ import (
// pairs in a Go map in-memory. The map is protected by a mutex.
type MemoryStorage struct {
fs map[string][]byte
- mu sync.Mutex
}
// OpenMemory opens a new MemoryStorage instance with internal map of 'size'.
func OpenMemory(size int) *MemoryStorage {
return &MemoryStorage{
fs: make(map[string][]byte, size),
- mu: sync.Mutex{},
}
}
@@ -30,33 +27,19 @@ func (st *MemoryStorage) Clean() error {
// ReadBytes implements Storage.ReadBytes().
func (st *MemoryStorage) ReadBytes(key string) ([]byte, error) {
- // Safely check store
- st.mu.Lock()
b, ok := st.fs[key]
- st.mu.Unlock()
-
- // Return early if not exist
if !ok {
return nil, ErrNotFound
}
-
- // Create return copy
return bytes.Copy(b), nil
}
// ReadStream implements Storage.ReadStream().
func (st *MemoryStorage) ReadStream(key string) (io.ReadCloser, error) {
- // Safely check store
- st.mu.Lock()
b, ok := st.fs[key]
- st.mu.Unlock()
-
- // Return early if not exist
if !ok {
return nil, ErrNotFound
}
-
- // Create io.ReadCloser from 'b' copy
b = bytes.Copy(b)
r := bytes.NewReader(b)
return util.NopReadCloser(r), nil
@@ -64,68 +47,43 @@ func (st *MemoryStorage) ReadStream(key string) (io.ReadCloser, error) {
// WriteBytes implements Storage.WriteBytes().
func (st *MemoryStorage) WriteBytes(key string, b []byte) error {
- // Safely check store
- st.mu.Lock()
_, ok := st.fs[key]
-
- // Check for already exist
if ok {
- st.mu.Unlock()
return ErrAlreadyExists
}
-
- // Write + unlock
st.fs[key] = bytes.Copy(b)
- st.mu.Unlock()
return nil
}
// WriteStream implements Storage.WriteStream().
func (st *MemoryStorage) WriteStream(key string, r io.Reader) error {
- // Read all from reader
b, err := io.ReadAll(r)
if err != nil {
return err
}
-
- // Write to storage
return st.WriteBytes(key, b)
}
// Stat implements Storage.Stat().
func (st *MemoryStorage) Stat(key string) (bool, error) {
- st.mu.Lock()
_, ok := st.fs[key]
- st.mu.Unlock()
return ok, nil
}
// Remove implements Storage.Remove().
func (st *MemoryStorage) Remove(key string) error {
- // Safely check store
- st.mu.Lock()
_, ok := st.fs[key]
-
- // Check in store
if !ok {
- st.mu.Unlock()
return ErrNotFound
}
-
- // Delete + unlock
delete(st.fs, key)
- st.mu.Unlock()
return nil
}
// WalkKeys implements Storage.WalkKeys().
func (st *MemoryStorage) WalkKeys(opts WalkKeysOptions) error {
- // Safely walk storage keys
- st.mu.Lock()
for key := range st.fs {
opts.WalkFn(entry(key))
}
- st.mu.Unlock()
-
return nil
}
diff --git a/vendor/codeberg.org/gruf/go-store/util/fs.go b/vendor/codeberg.org/gruf/go-store/util/fs.go
index fa6a9d2c4..93b37a261 100644
--- a/vendor/codeberg.org/gruf/go-store/util/fs.go
+++ b/vendor/codeberg.org/gruf/go-store/util/fs.go
@@ -9,14 +9,22 @@ import (
"codeberg.org/gruf/go-fastpath"
)
-var dotdot = "../"
+// IsDirTraversal will check if rootPlusPath is a dir traversal outside of root,
+// assuming that both are cleaned and that rootPlusPath is path.Join(root, somePath)
+func IsDirTraversal(root string, rootPlusPath string) bool {
+ switch {
+ // Root is $PWD, check for traversal out of
+ case root == ".":
+ return strings.HasPrefix(rootPlusPath, "../")
-// CountDotdots returns the number of "dot-dots" (../) in a cleaned filesystem path
-func CountDotdots(path string) int {
- if !strings.HasSuffix(path, dotdot) {
- return 0
+ // The path MUST be prefixed by root
+ case !strings.HasPrefix(rootPlusPath, root):
+ return true
+
+ // In all other cases, check not equal
+ default:
+ return len(root) == len(rootPlusPath)
}
- return strings.Count(path, dotdot)
}
// WalkDir traverses the dir tree of the supplied path, performing the supplied walkFn on each entry