Fix setting pointers corrupting config in memory (#4868)

This commit is contained in:
WithoutPants
2024-05-23 10:56:18 +10:00
committed by GitHub
parent 77ef16570b
commit 4794a1d453
8 changed files with 238 additions and 287 deletions

View File

@@ -381,10 +381,6 @@ func (i *Config) GetNotificationsEnabled() bool {
return i.getBool(NotificationsEnabled)
}
// func (i *Instance) GetConfigUpdatesChannel() chan int {
// return i.configUpdates
// }
// GetShowOneTimeMovedNotification shows whether a small notification to inform the user that Stash
// will no longer show a terminal window, and instead will be available in the tray, should be shown.
// It is true when an existing system is started after upgrading, and set to false forever after it is shown.
@@ -392,10 +388,24 @@ func (i *Config) GetShowOneTimeMovedNotification() bool {
return i.getBool(ShowOneTimeMovedNotification)
}
func (i *Config) Set(key string, value interface{}) {
// if key == MenuItems {
// i.configUpdates <- 0
// }
// these methods are intended to ensure type safety (ie no primitive pointers)
func (i *Config) SetBool(key string, value bool) {
i.SetInterface(key, value)
}
func (i *Config) SetString(key string, value string) {
i.SetInterface(key, value)
}
func (i *Config) SetInt(key string, value int) {
i.SetInterface(key, value)
}
func (i *Config) SetFloat(key string, value float64) {
i.SetInterface(key, value)
}
func (i *Config) SetInterface(key string, value interface{}) {
i.Lock()
defer i.Unlock()
@@ -438,9 +448,9 @@ func (i *Config) setDefault(key string, value interface{}) {
func (i *Config) SetPassword(value string) {
// if blank, don't bother hashing; we want it to be blank
if value == "" {
i.Set(Password, "")
i.SetString(Password, "")
} else {
i.Set(Password, hashPassword(value))
i.SetString(Password, hashPassword(value))
}
}
@@ -1624,7 +1634,7 @@ func (i *Config) GetNoProxy() string {
// config field to the provided IP address to indicate that stash has been accessed
// from this public IP without authentication.
func (i *Config) ActivatePublicAccessTripwire(requestIP string) error {
i.Set(SecurityTripwireAccessedFromPublicInternet, requestIP)
i.SetString(SecurityTripwireAccessedFromPublicInternet, requestIP)
return i.Write()
}
@@ -1807,7 +1817,7 @@ func (i *Config) SetInitialConfig() error {
if err != nil {
return fmt.Errorf("error generating JWTSignKey: %w", err)
}
i.Set(JWTSignKey, signKey)
i.SetString(JWTSignKey, signKey)
}
if string(i.GetSessionStoreKey()) == "" {
@@ -1815,7 +1825,7 @@ func (i *Config) SetInitialConfig() error {
if err != nil {
return fmt.Errorf("error generating session store key: %w", err)
}
i.Set(SessionStoreKey, sessionStoreKey)
i.SetString(SessionStoreKey, sessionStoreKey)
}
i.setDefaultValues()

View File

@@ -27,101 +27,101 @@ func TestConcurrentConfigAccess(t *testing.T) {
i.GetConfigFile()
i.GetConfigPath()
i.GetDefaultDatabaseFilePath()
i.Set(BackupDirectoryPath, i.GetBackupDirectoryPath())
i.SetInterface(BackupDirectoryPath, i.GetBackupDirectoryPath())
i.GetStashPaths()
_ = i.ValidateStashBoxes(nil)
_ = i.Validate()
_ = i.ActivatePublicAccessTripwire("")
i.Set(Cache, i.GetCachePath())
i.Set(Generated, i.GetGeneratedPath())
i.Set(Metadata, i.GetMetadataPath())
i.Set(Database, i.GetDatabasePath())
i.SetInterface(Cache, i.GetCachePath())
i.SetInterface(Generated, i.GetGeneratedPath())
i.SetInterface(Metadata, i.GetMetadataPath())
i.SetInterface(Database, i.GetDatabasePath())
// these must be set as strings since the original values are also strings
// setting them as []byte will cause the returned string to be corrupted
i.Set(JWTSignKey, string(i.GetJWTSignKey()))
i.Set(SessionStoreKey, string(i.GetSessionStoreKey()))
i.SetInterface(JWTSignKey, string(i.GetJWTSignKey()))
i.SetInterface(SessionStoreKey, string(i.GetSessionStoreKey()))
i.GetDefaultScrapersPath()
i.Set(Exclude, i.GetExcludes())
i.Set(ImageExclude, i.GetImageExcludes())
i.Set(VideoExtensions, i.GetVideoExtensions())
i.Set(ImageExtensions, i.GetImageExtensions())
i.Set(GalleryExtensions, i.GetGalleryExtensions())
i.Set(CreateGalleriesFromFolders, i.GetCreateGalleriesFromFolders())
i.Set(Language, i.GetLanguage())
i.Set(VideoFileNamingAlgorithm, i.GetVideoFileNamingAlgorithm())
i.Set(ScrapersPath, i.GetScrapersPath())
i.Set(ScraperUserAgent, i.GetScraperUserAgent())
i.Set(ScraperCDPPath, i.GetScraperCDPPath())
i.Set(ScraperCertCheck, i.GetScraperCertCheck())
i.Set(ScraperExcludeTagPatterns, i.GetScraperExcludeTagPatterns())
i.Set(StashBoxes, i.GetStashBoxes())
i.SetInterface(Exclude, i.GetExcludes())
i.SetInterface(ImageExclude, i.GetImageExcludes())
i.SetInterface(VideoExtensions, i.GetVideoExtensions())
i.SetInterface(ImageExtensions, i.GetImageExtensions())
i.SetInterface(GalleryExtensions, i.GetGalleryExtensions())
i.SetInterface(CreateGalleriesFromFolders, i.GetCreateGalleriesFromFolders())
i.SetInterface(Language, i.GetLanguage())
i.SetInterface(VideoFileNamingAlgorithm, i.GetVideoFileNamingAlgorithm())
i.SetInterface(ScrapersPath, i.GetScrapersPath())
i.SetInterface(ScraperUserAgent, i.GetScraperUserAgent())
i.SetInterface(ScraperCDPPath, i.GetScraperCDPPath())
i.SetInterface(ScraperCertCheck, i.GetScraperCertCheck())
i.SetInterface(ScraperExcludeTagPatterns, i.GetScraperExcludeTagPatterns())
i.SetInterface(StashBoxes, i.GetStashBoxes())
i.GetDefaultPluginsPath()
i.Set(PluginsPath, i.GetPluginsPath())
i.Set(Host, i.GetHost())
i.Set(Port, i.GetPort())
i.Set(ExternalHost, i.GetExternalHost())
i.Set(PreviewSegmentDuration, i.GetPreviewSegmentDuration())
i.Set(ParallelTasks, i.GetParallelTasks())
i.Set(ParallelTasks, i.GetParallelTasksWithAutoDetection())
i.Set(PreviewAudio, i.GetPreviewAudio())
i.Set(PreviewSegments, i.GetPreviewSegments())
i.Set(PreviewExcludeStart, i.GetPreviewExcludeStart())
i.Set(PreviewExcludeEnd, i.GetPreviewExcludeEnd())
i.Set(PreviewPreset, i.GetPreviewPreset())
i.Set(MaxTranscodeSize, i.GetMaxTranscodeSize())
i.Set(MaxStreamingTranscodeSize, i.GetMaxStreamingTranscodeSize())
i.Set(ApiKey, i.GetAPIKey())
i.Set(Username, i.GetUsername())
i.Set(Password, i.GetPasswordHash())
i.SetInterface(PluginsPath, i.GetPluginsPath())
i.SetInterface(Host, i.GetHost())
i.SetInterface(Port, i.GetPort())
i.SetInterface(ExternalHost, i.GetExternalHost())
i.SetInterface(PreviewSegmentDuration, i.GetPreviewSegmentDuration())
i.SetInterface(ParallelTasks, i.GetParallelTasks())
i.SetInterface(ParallelTasks, i.GetParallelTasksWithAutoDetection())
i.SetInterface(PreviewAudio, i.GetPreviewAudio())
i.SetInterface(PreviewSegments, i.GetPreviewSegments())
i.SetInterface(PreviewExcludeStart, i.GetPreviewExcludeStart())
i.SetInterface(PreviewExcludeEnd, i.GetPreviewExcludeEnd())
i.SetInterface(PreviewPreset, i.GetPreviewPreset())
i.SetInterface(MaxTranscodeSize, i.GetMaxTranscodeSize())
i.SetInterface(MaxStreamingTranscodeSize, i.GetMaxStreamingTranscodeSize())
i.SetInterface(ApiKey, i.GetAPIKey())
i.SetInterface(Username, i.GetUsername())
i.SetInterface(Password, i.GetPasswordHash())
i.GetCredentials()
i.Set(MaxSessionAge, i.GetMaxSessionAge())
i.Set(CustomServedFolders, i.GetCustomServedFolders())
i.Set(LegacyCustomUILocation, i.GetUILocation())
i.Set(MenuItems, i.GetMenuItems())
i.Set(SoundOnPreview, i.GetSoundOnPreview())
i.Set(WallShowTitle, i.GetWallShowTitle())
i.Set(CustomPerformerImageLocation, i.GetCustomPerformerImageLocation())
i.Set(WallPlayback, i.GetWallPlayback())
i.Set(MaximumLoopDuration, i.GetMaximumLoopDuration())
i.Set(AutostartVideo, i.GetAutostartVideo())
i.Set(ShowStudioAsText, i.GetShowStudioAsText())
i.Set(legacyImageLightboxSlideshowDelay, *i.GetImageLightboxOptions().SlideshowDelay)
i.Set(ImageLightboxSlideshowDelay, *i.GetImageLightboxOptions().SlideshowDelay)
i.SetInterface(MaxSessionAge, i.GetMaxSessionAge())
i.SetInterface(CustomServedFolders, i.GetCustomServedFolders())
i.SetInterface(LegacyCustomUILocation, i.GetUILocation())
i.SetInterface(MenuItems, i.GetMenuItems())
i.SetInterface(SoundOnPreview, i.GetSoundOnPreview())
i.SetInterface(WallShowTitle, i.GetWallShowTitle())
i.SetInterface(CustomPerformerImageLocation, i.GetCustomPerformerImageLocation())
i.SetInterface(WallPlayback, i.GetWallPlayback())
i.SetInterface(MaximumLoopDuration, i.GetMaximumLoopDuration())
i.SetInterface(AutostartVideo, i.GetAutostartVideo())
i.SetInterface(ShowStudioAsText, i.GetShowStudioAsText())
i.SetInterface(legacyImageLightboxSlideshowDelay, *i.GetImageLightboxOptions().SlideshowDelay)
i.SetInterface(ImageLightboxSlideshowDelay, *i.GetImageLightboxOptions().SlideshowDelay)
i.GetCSSPath()
i.GetCSS()
i.GetJavascriptPath()
i.GetJavascript()
i.GetCustomLocalesPath()
i.GetCustomLocales()
i.Set(CSSEnabled, i.GetCSSEnabled())
i.Set(CSSEnabled, i.GetCustomLocalesEnabled())
i.Set(HandyKey, i.GetHandyKey())
i.Set(UseStashHostedFunscript, i.GetUseStashHostedFunscript())
i.Set(DLNAServerName, i.GetDLNAServerName())
i.Set(DLNADefaultEnabled, i.GetDLNADefaultEnabled())
i.Set(DLNADefaultIPWhitelist, i.GetDLNADefaultIPWhitelist())
i.Set(DLNAInterfaces, i.GetDLNAInterfaces())
i.Set(DLNAPort, i.GetDLNAPort())
i.Set(LogFile, i.GetLogFile())
i.Set(LogOut, i.GetLogOut())
i.Set(LogLevel, i.GetLogLevel())
i.Set(LogAccess, i.GetLogAccess())
i.Set(MaxUploadSize, i.GetMaxUploadSize())
i.Set(FunscriptOffset, i.GetFunscriptOffset())
i.Set(DefaultIdentifySettings, i.GetDefaultIdentifySettings())
i.Set(DeleteGeneratedDefault, i.GetDeleteGeneratedDefault())
i.Set(DeleteFileDefault, i.GetDeleteFileDefault())
i.Set(dangerousAllowPublicWithoutAuth, i.GetDangerousAllowPublicWithoutAuth())
i.Set(SecurityTripwireAccessedFromPublicInternet, i.GetSecurityTripwireAccessedFromPublicInternet())
i.Set(DisableDropdownCreatePerformer, i.GetDisableDropdownCreate().Performer)
i.Set(DisableDropdownCreateStudio, i.GetDisableDropdownCreate().Studio)
i.Set(DisableDropdownCreateTag, i.GetDisableDropdownCreate().Tag)
i.Set(DisableDropdownCreateMovie, i.GetDisableDropdownCreate().Movie)
i.Set(AutostartVideoOnPlaySelected, i.GetAutostartVideoOnPlaySelected())
i.Set(ContinuePlaylistDefault, i.GetContinuePlaylistDefault())
i.Set(PythonPath, i.GetPythonPath())
i.SetInterface(CSSEnabled, i.GetCSSEnabled())
i.SetInterface(CSSEnabled, i.GetCustomLocalesEnabled())
i.SetInterface(HandyKey, i.GetHandyKey())
i.SetInterface(UseStashHostedFunscript, i.GetUseStashHostedFunscript())
i.SetInterface(DLNAServerName, i.GetDLNAServerName())
i.SetInterface(DLNADefaultEnabled, i.GetDLNADefaultEnabled())
i.SetInterface(DLNADefaultIPWhitelist, i.GetDLNADefaultIPWhitelist())
i.SetInterface(DLNAInterfaces, i.GetDLNAInterfaces())
i.SetInterface(DLNAPort, i.GetDLNAPort())
i.SetInterface(LogFile, i.GetLogFile())
i.SetInterface(LogOut, i.GetLogOut())
i.SetInterface(LogLevel, i.GetLogLevel())
i.SetInterface(LogAccess, i.GetLogAccess())
i.SetInterface(MaxUploadSize, i.GetMaxUploadSize())
i.SetInterface(FunscriptOffset, i.GetFunscriptOffset())
i.SetInterface(DefaultIdentifySettings, i.GetDefaultIdentifySettings())
i.SetInterface(DeleteGeneratedDefault, i.GetDeleteGeneratedDefault())
i.SetInterface(DeleteFileDefault, i.GetDeleteFileDefault())
i.SetInterface(dangerousAllowPublicWithoutAuth, i.GetDangerousAllowPublicWithoutAuth())
i.SetInterface(SecurityTripwireAccessedFromPublicInternet, i.GetSecurityTripwireAccessedFromPublicInternet())
i.SetInterface(DisableDropdownCreatePerformer, i.GetDisableDropdownCreate().Performer)
i.SetInterface(DisableDropdownCreateStudio, i.GetDisableDropdownCreate().Studio)
i.SetInterface(DisableDropdownCreateTag, i.GetDisableDropdownCreate().Tag)
i.SetInterface(DisableDropdownCreateMovie, i.GetDisableDropdownCreate().Movie)
i.SetInterface(AutostartVideoOnPlaySelected, i.GetAutostartVideoOnPlaySelected())
i.SetInterface(ContinuePlaylistDefault, i.GetContinuePlaylistDefault())
i.SetInterface(PythonPath, i.GetPythonPath())
t.Logf("Worker %v iteration %v took %v", wk, l, time.Since(start))
}
wg.Done()

View File

@@ -245,7 +245,7 @@ func (s *Manager) Setup(ctx context.Context, input SetupInput) error {
}
}
s.Config.Set(config.Generated, input.GeneratedLocation)
s.Config.SetString(config.Generated, input.GeneratedLocation)
}
// create the cache directory if it does not exist
@@ -256,11 +256,11 @@ func (s *Manager) Setup(ctx context.Context, input SetupInput) error {
}
}
cfg.Set(config.Cache, input.CacheLocation)
cfg.SetString(config.Cache, input.CacheLocation)
}
if input.StoreBlobsInDatabase {
cfg.Set(config.BlobsStorage, config.BlobStorageTypeDatabase)
cfg.SetInterface(config.BlobsStorage, config.BlobStorageTypeDatabase)
} else {
if !cfg.HasOverride(config.BlobsPath) {
if exists, _ := fsutil.DirExists(input.BlobsLocation); !exists {
@@ -269,18 +269,18 @@ func (s *Manager) Setup(ctx context.Context, input SetupInput) error {
}
}
cfg.Set(config.BlobsPath, input.BlobsLocation)
cfg.SetString(config.BlobsPath, input.BlobsLocation)
}
cfg.Set(config.BlobsStorage, config.BlobStorageTypeFilesystem)
cfg.SetInterface(config.BlobsStorage, config.BlobStorageTypeFilesystem)
}
// set the configuration
if !cfg.HasOverride(config.Database) {
cfg.Set(config.Database, input.DatabaseFile)
cfg.SetString(config.Database, input.DatabaseFile)
}
cfg.Set(config.Stash, input.Stashes)
cfg.SetInterface(config.Stash, input.Stashes)
if err := cfg.Write(); err != nil {
return fmt.Errorf("error writing configuration file: %v", err)