thomiceli / opengist

Self-hosted pastebin powered by Git, open-source alternative to Github Gist.
https://demo.opengist.io
GNU Affero General Public License v3.0
1.52k stars 76 forks source link

Using golang.org/x/text/cases.Caser.String concurrently may cause panic #298

Open angela0 opened 4 weeks ago

angela0 commented 4 weeks ago

Sometimes opengist panics at internal/web/util.go:119 s = title.String(s) (tag: v1.7.3). I found golang.org/x/text/cases.Caser.String can't be called concurrently. Here is an example:

// go version go1.22.4 linux/amd64

    title := cases.Title(language.English)
    for {
        go func() {
            title.String("Abc fgt")
        }()
    }

So I move all var title = cases.Title(language.English) codes to title.String(...) as below and panics disappear.

diff file(base tag v1.7.3):

diff --git a/internal/i18n/locale.go b/internal/i18n/locale.go
index e4721cd..90e3651 100644
--- a/internal/i18n/locale.go
+++ b/internal/i18n/locale.go
@@ -14,7 +14,6 @@ import (
    "strings"
 )

-var title = cases.Title(language.English)
 var Locales = NewLocaleStore()

 type LocaleStore struct {
@@ -59,7 +58,7 @@ func (store *LocaleStore) loadLocaleFromYAML(localeCode, path string) error {

    locale := &Locale{
        Code:     localeCode,
-       Name:     title.String(name),
+       Name:     cases.Title(language.English).String(name),
        Messages: make(map[string]string),
    }

diff --git a/internal/web/auth.go b/internal/web/auth.go
index 1b4ff79..2947363 100644
--- a/internal/web/auth.go
+++ b/internal/web/auth.go
@@ -34,8 +34,6 @@ const (
    OpenIDConnect  = "openid-connect"
 )

-var title = cases.Title(language.English)
-
 func register(ctx echo.Context) error {
    disableSignup := getData(ctx, "DisableSignup")
    disableForm := getData(ctx, "DisableLoginForm")
@@ -188,10 +186,10 @@ func oauthCallback(ctx echo.Context) error {
        updateUserProviderInfo(currUser, user.Provider, user)

        if err = currUser.Update(); err != nil {
-           return errorRes(500, "Cannot update user "+title.String(user.Provider)+" id", err)
+           return errorRes(500, "Cannot update user "+cases.Title(language.English).String(user.Provider)+" id", err)
        }

-       addFlash(ctx, tr(ctx, "flash.auth.account-linked-oauth", title.String(user.Provider)), "success")
+       addFlash(ctx, tr(ctx, "flash.auth.account-linked-oauth", cases.Title(language.English).String(user.Provider)), "success")
        return redirect(ctx, "/settings")
    }

@@ -336,7 +334,6 @@ func oauth(ctx echo.Context) error {
            "email",
            "profile",
        )
-
        if err != nil {
            return errorRes(500, "Cannot create OIDC provider", err)
        }
@@ -358,10 +355,10 @@ func oauth(ctx echo.Context) error {
        // Means that the user wants to unlink the account
        if checkFunc, exists := providerIDCheckMap[provider]; exists && checkFunc() {
            if err := currUser.DeleteProviderID(provider); err != nil {
-               return errorRes(500, "Cannot unlink account from "+title.String(provider), err)
+               return errorRes(500, "Cannot unlink account from "+cases.Title(language.English).String(provider), err)
            }

-           addFlash(ctx, tr(ctx, "flash.auth.account-unlinked-oauth", title.String(provider)), "success")
+           addFlash(ctx, tr(ctx, "flash.auth.account-unlinked-oauth", cases.Title(language.English).String(provider)), "success")
            return redirect(ctx, "/settings")
        }
    }
diff --git a/internal/web/util.go b/internal/web/util.go
index 3935c41..732ed96 100644
--- a/internal/web/util.go
+++ b/internal/web/util.go
@@ -8,6 +8,8 @@ import (
    "github.com/thomiceli/opengist/internal/config"
    "github.com/thomiceli/opengist/internal/db"
    "github.com/thomiceli/opengist/internal/i18n"
+   "golang.org/x/text/cases"
+   "golang.org/x/text/language"
    "html/template"
    "net/http"
    "strconv"
@@ -116,7 +118,7 @@ func loadSettings(ctx echo.Context) error {

    for key, value := range settings {
        s := strings.ReplaceAll(key, "-", " ")
-       s = title.String(s)
+       s = cases.Title(language.English).String(s)
        setData(ctx, strings.ReplaceAll(s, " ", ""), value == "1")
    }
    return nil

I do not read the code in detail and cannot guarantee the correctness of my code. , so I don't open a pull request.