From 489c36b10108a9dfc71fe13a3e37f2b90fcf113d Mon Sep 17 00:00:00 2001
From: nielash <nielronash@gmail.com>
Date: Thu, 21 Dec 2023 14:06:06 -0500
Subject: [PATCH] hasher: fix invalid memory address error when MaxAge == 0

When f.opt.MaxAge == 0, f.db is never set, however several methods later assume
it is set and attempt to access it, causing an invalid memory address error.
This change fixes the issue in a few spots (there may still be others I haven't
yet encountered.)
---
 backend/hasher/commands.go             | 8 ++++++++
 backend/hasher/hasher.go               | 4 +++-
 backend/hasher/hasher_internal_test.go | 8 +++++---
 backend/hasher/hasher_test.go          | 5 +++++
 lib/kv/bolt.go                         | 2 +-
 5 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/backend/hasher/commands.go b/backend/hasher/commands.go
index 517ab17cc..a6eff7efd 100644
--- a/backend/hasher/commands.go
+++ b/backend/hasher/commands.go
@@ -80,6 +80,14 @@ func (f *Fs) dbDump(ctx context.Context, full bool, root string) error {
 		}
 		root = fspath.JoinRootPath(remoteFs.Root(), f.Root())
 	}
+	if f.db == nil {
+		if f.opt.MaxAge == 0 {
+			fs.Errorf(f, "db not found. (disabled with max_age = 0)")
+		} else {
+			fs.Errorf(f, "db not found.")
+		}
+		return kv.ErrInactive
+	}
 	op := &kvDump{
 		full: full,
 		root: root,
diff --git a/backend/hasher/hasher.go b/backend/hasher/hasher.go
index 325f7f619..a6e83039f 100644
--- a/backend/hasher/hasher.go
+++ b/backend/hasher/hasher.go
@@ -418,7 +418,9 @@ func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string
 
 // Shutdown the backend, closing any background tasks and any cached connections.
 func (f *Fs) Shutdown(ctx context.Context) (err error) {
-	err = f.db.Stop(false)
+	if f.db != nil {
+		err = f.db.Stop(false)
+	}
 	if do := f.Fs.Features().Shutdown; do != nil {
 		if err2 := do(ctx); err2 != nil {
 			err = err2
diff --git a/backend/hasher/hasher_internal_test.go b/backend/hasher/hasher_internal_test.go
index 0ca418e20..e289d8f0d 100644
--- a/backend/hasher/hasher_internal_test.go
+++ b/backend/hasher/hasher_internal_test.go
@@ -60,9 +60,11 @@ func (f *Fs) testUploadFromCrypt(t *testing.T) {
 	assert.NotNil(t, dst)
 
 	// check that hash was created
-	hash, err = f.getRawHash(ctx, hashType, fileName, anyFingerprint, longTime)
-	assert.NoError(t, err)
-	assert.NotEmpty(t, hash)
+	if f.opt.MaxAge > 0 {
+		hash, err = f.getRawHash(ctx, hashType, fileName, anyFingerprint, longTime)
+		assert.NoError(t, err)
+		assert.NotEmpty(t, hash)
+	}
 	//t.Logf("hash is %q", hash)
 	_ = operations.Purge(ctx, f, dirName)
 }
diff --git a/backend/hasher/hasher_test.go b/backend/hasher/hasher_test.go
index f17303ecc..f5119c724 100644
--- a/backend/hasher/hasher_test.go
+++ b/backend/hasher/hasher_test.go
@@ -37,4 +37,9 @@ func TestIntegration(t *testing.T) {
 		opt.QuickTestOK = true
 	}
 	fstests.Run(t, &opt)
+	// test again with MaxAge = 0
+	if *fstest.RemoteName == "" {
+		opt.ExtraConfig = append(opt.ExtraConfig, fstests.ExtraConfigItem{Name: "TestHasher", Key: "max_age", Value: "0"})
+		fstests.Run(t, &opt)
+	}
 }
diff --git a/lib/kv/bolt.go b/lib/kv/bolt.go
index 6fcfe49dd..2a411c3dd 100644
--- a/lib/kv/bolt.go
+++ b/lib/kv/bolt.go
@@ -216,7 +216,7 @@ func (db *DB) loop() {
 
 // Do a key-value operation and return error when done
 func (db *DB) Do(write bool, op Op) error {
-	if db.queue == nil {
+	if db == nil || db.queue == nil {
 		return ErrInactive
 	}
 	r := &request{