Skip to content

Commit 42a3ff8

Browse files
authored
[3.2.5 Backport] CBG-4659: Uptake Otto stack depth limit with tests (#7541)
1 parent 33a5ed5 commit 42a3ff8

File tree

5 files changed

+42
-4
lines changed

5 files changed

+42
-4
lines changed

channels/channelmapper_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,3 +663,12 @@ func TestGetDefaultSyncFunction(t *testing.T) {
663663
})
664664
}
665665
}
666+
667+
// TestSyncFunctionRecursion ensures that an infinite recursion in the sync function does not cause a stack overflow.
668+
func TestSyncFunctionRecursion(t *testing.T) {
669+
ctx := base.TestCtx(t)
670+
mapper := NewChannelMapper(ctx, `function access(doc) { access("foo", "bar"); }`, 0)
671+
res, err := mapper.MapToChannelsAndAccess(ctx, parse(t, `{"blank": "doc"}`), `{}`, emptyMetaMap(), noUser)
672+
require.ErrorContains(t, err, "Maximum call stack size exceeded")
673+
require.Nil(t, res)
674+
}

channels/main_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func TestMain(m *testing.M) {
2424
teardownFuncs := make([]func(), 0)
2525
teardownFuncs = append(teardownFuncs, base.SetUpGlobalTestLogging(ctx))
2626
teardownFuncs = append(teardownFuncs, base.SetUpGlobalTestProfiling(m))
27-
teardownFuncs = append(teardownFuncs, base.SetUpGlobalTestMemoryWatermark(m, 128))
27+
teardownFuncs = append(teardownFuncs, base.SetUpGlobalTestMemoryWatermark(m, 256))
2828

2929
base.SkipPrometheusStatsRegistration = true
3030

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ require (
1313
github.com/couchbase/gocbcore/v10 v10.5.4-0.20250107135314-f4c4becdca29
1414
github.com/couchbase/gomemcached v0.2.1
1515
github.com/couchbase/goutils v0.1.2
16-
github.com/couchbase/sg-bucket v0.0.0-20241018143914-45ef51a0c1be
16+
github.com/couchbase/sg-bucket v0.0.0-20250522135601-8c9a5acda2c2
1717
github.com/couchbaselabs/go-fleecedelta v0.0.0-20220909152808-6d09efa7a338
1818
github.com/couchbaselabs/gocbconnstr v1.0.5
1919
github.com/couchbaselabs/rosmar v0.0.0-20240610211258-c856107e8e78

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ github.com/couchbase/goprotostellar v1.0.2 h1:yoPbAL9sCtcyZ5e/DcU5PRMOEFaJrF9awX
5454
github.com/couchbase/goprotostellar v1.0.2/go.mod h1:5/yqVnZlW2/NSbAWu1hPJCFBEwjxgpe0PFFOlRixnp4=
5555
github.com/couchbase/goutils v0.1.2 h1:gWr8B6XNWPIhfalHNog3qQKfGiYyh4K4VhO3P2o9BCs=
5656
github.com/couchbase/goutils v0.1.2/go.mod h1:h89Ek/tiOxxqjz30nPPlwZdQbdB8BwgnuBxeoUe/ViE=
57-
github.com/couchbase/sg-bucket v0.0.0-20241018143914-45ef51a0c1be h1:QM2afa9Xhbhy1ywVEVCRV0vEQvHIPplDkc6NsNug78Y=
58-
github.com/couchbase/sg-bucket v0.0.0-20241018143914-45ef51a0c1be/go.mod h1:Tw3QSBP+nkDjw1cpHwMFP4pBORs0UOP+KbF2hXBVwqM=
57+
github.com/couchbase/sg-bucket v0.0.0-20250522135601-8c9a5acda2c2 h1:K8PMVrRNknzTMo+Blg1d0kVhyZzcdcmKpFb6scp/0NA=
58+
github.com/couchbase/sg-bucket v0.0.0-20250522135601-8c9a5acda2c2/go.mod h1:Tw3QSBP+nkDjw1cpHwMFP4pBORs0UOP+KbF2hXBVwqM=
5959
github.com/couchbase/tools-common/cloud v1.0.0 h1:SQZIccXoedbrThehc/r9BJbpi/JhwJ8X00PDjZ2gEBE=
6060
github.com/couchbase/tools-common/cloud v1.0.0/go.mod h1:6KVlRpbcnDWrvickUJ+xpqCWx1vgYYlEli/zL4xmZAg=
6161
github.com/couchbase/tools-common/fs v1.0.0 h1:HFA4xCF/r3BtZShFJUxzVvGuXtDkqGnaPzYJP3Kp1mw=

rest/importtest/import_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,35 @@ func TestImportFeed(t *testing.T) {
7373
assert.Equal(t, int64(1), rt.GetDatabase().DbStats.SharedBucketImportStats.ImportCount.Value())
7474
}
7575

76+
func TestImportFeedWithRecursiveSyncFunction(t *testing.T) {
77+
base.SkipImportTestsIfNotEnabled(t)
78+
79+
base.SetUpTestLogging(t, base.LevelDebug, base.KeyImport, base.KeyCRUD)
80+
81+
rt := rest.NewRestTester(t, &rest.RestTesterConfig{
82+
SyncFn: `function access(doc) { access("foo", "bar"); }`,
83+
AutoImport: base.Ptr(true),
84+
})
85+
defer rt.Close()
86+
87+
// Create doc via the SDK
88+
mobileKey := t.Name()
89+
mobileBody := map[string]any{"channels": "ABC"}
90+
added, err := rt.GetSingleDataStore().Add(mobileKey, 0, mobileBody)
91+
require.NoError(t, err, "Error writing SDK doc")
92+
require.True(t, added)
93+
94+
base.RequireWaitForStat(t, rt.GetDatabase().DbStats.SharedBucketImportStats.ImportErrorCount.Value, 1)
95+
96+
// Attempt to get the document via Sync Gateway.
97+
response := rt.SendAdminRequest("GET", "/{{.keyspace}}/"+mobileKey, "")
98+
assert.Equal(t, 404, response.Code)
99+
100+
// Verify this didn't trigger an on-demand import
101+
assert.Equal(t, int64(0), rt.GetDatabase().DbStats.SharedBucketImportStats.ImportCount.Value())
102+
base.RequireWaitForStat(t, rt.GetDatabase().DbStats.SharedBucketImportStats.ImportErrorCount.Value, 2)
103+
}
104+
76105
// Test import of an SDK delete.
77106
func TestXattrImportOldDoc(t *testing.T) {
78107
rtConfig := rest.RestTesterConfig{

0 commit comments

Comments
 (0)