bugfix: protect field access with lock to avoid possible data race (#5211)

This commit is contained in:
Stone-afk 2023-05-18 21:22:41 +08:00 committed by Ming Deng
parent f61065d674
commit 4e481606f7
12 changed files with 81 additions and 98 deletions

View File

@ -9,6 +9,7 @@
- [Fix 5079: only log msg when the channel is not closed](https://github.com/beego/beego/pull/5132)
- [Fix 4435: Controller SaveToFile remove all temp file](https://github.com/beego/beego/pull/5138)
- [Fix 5079: Split signalChan into flushChan and closeChan](https://github.com/beego/beego/pull/5139)
- [Fix 5172: protect field access with lock to avoid possible data race](https://github.com/beego/beego/pull/5210)
# v2.0.7
- [Upgrade github.com/go-kit/kit, CVE-2022-24450](https://github.com/beego/beego/pull/5121)

View File

@ -1,54 +0,0 @@
## cache
cache is a Go cache manager. It can use many cache adapters. The repo is inspired by `database/sql` .
## How to install?
go get github.com/beego/beego/v2/client/cache
## What adapters are supported?
As of now this cache support memory, Memcache and Redis.
## How to use it?
First you must import it
import (
"github.com/beego/beego/v2/client/cache"
)
Then init a Cache (example with memory adapter)
bm, err := cache.NewCache("memory", `{"interval":60}`)
Use it like this:
bm.Put("astaxie", 1, 10 * time.Second)
bm.Get("astaxie")
bm.IsExist("astaxie")
bm.Delete("astaxie")
## Memory adapter
Configure memory adapter like this:
{"interval":60}
interval means the gc time. The cache will check at each time interval, whether item has expired.
## Memcache adapter
Memcache adapter use the [gomemcache](http://github.com/bradfitz/gomemcache) client.
Configure like this:
{"conn":"127.0.0.1:11211"}
## Redis adapter
Redis adapter use the [redigo](http://github.com/gomodule/redigo) client.
Configure like this:
{"conn":":6039"}

View File

@ -20,15 +20,16 @@
//
// Usage:
// import(
//
// _ "github.com/beego/beego/v2/server/web/session/couchbase"
// "github.com/beego/beego/v2/server/web/session"
//
// )
//
// func init() {
// globalSessions, _ = session.NewManager("couchbase", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"http://host:port/, Pool, Bucket"}``)
// go globalSessions.GC()
// }
//
package couchbase
import (
@ -105,8 +106,10 @@ func (cs *SessionStore) SessionID(context.Context) string {
// SessionRelease Write couchbase session with Gob string
func (cs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
defer cs.b.Close()
bo, err := session.EncodeGob(cs.values)
cs.lock.RLock()
values := cs.values
cs.lock.RUnlock()
bo, err := session.EncodeGob(values)
if err != nil {
return
}

View File

@ -69,7 +69,10 @@ func (ls *SessionStore) SessionID(context.Context) string {
// SessionRelease save session values to ledis
func (ls *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
b, err := session.EncodeGob(ls.values)
ls.lock.RLock()
values := ls.values
ls.lock.RUnlock()
b, err := session.EncodeGob(values)
if err != nil {
return
}

View File

@ -20,15 +20,16 @@
//
// Usage:
// import(
//
// _ "github.com/beego/beego/v2/server/web/session/memcache"
// "github.com/beego/beego/v2/server/web/session"
//
// )
//
// func init() {
// globalSessions, _ = session.NewManager("memcache", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:11211"}``)
// go globalSessions.GC()
// }
//
package memcache
import (
@ -96,7 +97,10 @@ func (rs *SessionStore) SessionID(context.Context) string {
// SessionRelease save session values to memcache
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
b, err := session.EncodeGob(rs.values)
rs.lock.RLock()
values := rs.values
rs.lock.RUnlock()
b, err := session.EncodeGob(values)
if err != nil {
return
}

View File

@ -19,6 +19,7 @@
// go install github.com/go-sql-driver/mysql
//
// mysql session support need create table as sql:
//
// CREATE TABLE `session` (
// `session_key` char(64) NOT NULL,
// `session_data` blob,
@ -28,15 +29,16 @@
//
// Usage:
// import(
//
// _ "github.com/beego/beego/v2/server/web/session/mysql"
// "github.com/beego/beego/v2/server/web/session"
//
// )
//
// func init() {
// globalSessions, _ = session.NewManager("mysql", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]"}``)
// go globalSessions.GC()
// }
//
package mysql
import (
@ -109,7 +111,10 @@ func (st *SessionStore) SessionID(context.Context) string {
// must call this method to save values to database.
func (st *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
defer st.c.Close()
b, err := session.EncodeGob(st.values)
st.lock.RLock()
values := st.values
st.lock.RUnlock()
b, err := session.EncodeGob(values)
if err != nil {
return
}

View File

@ -18,7 +18,6 @@
//
// go install github.com/lib/pq
//
//
// needs this table in your database:
//
// CREATE TABLE session (
@ -35,18 +34,18 @@
// SessionSavePath = "user=a password=b dbname=c sslmode=disable"
// SessionName = session
//
//
// Usage:
// import(
//
// _ "github.com/beego/beego/v2/server/web/session/postgresql"
// "github.com/beego/beego/v2/server/web/session"
//
// )
//
// func init() {
// globalSessions, _ = session.NewManager("postgresql", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"user=pqgotest dbname=pqgotest sslmode=verify-full"}``)
// go globalSessions.GC()
// }
//
package postgres
import (
@ -115,7 +114,10 @@ func (st *SessionStore) SessionID(context.Context) string {
// must call this method to save values to database.
func (st *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
defer st.c.Close()
b, err := session.EncodeGob(st.values)
st.lock.RLock()
values := st.values
st.lock.RUnlock()
b, err := session.EncodeGob(values)
if err != nil {
return
}

View File

@ -20,15 +20,16 @@
//
// Usage:
// import(
//
// _ "github.com/beego/beego/v2/server/web/session/redis"
// "github.com/beego/beego/v2/server/web/session"
//
// )
//
// func init() {
// globalSessions, _ = session.NewManager("redis", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070"}``)
// go globalSessions.GC()
// }
//
package redis
import (
@ -100,7 +101,10 @@ func (rs *SessionStore) SessionID(context.Context) string {
// SessionRelease save session values to redis
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
b, err := session.EncodeGob(rs.values)
rs.lock.RLock()
values := rs.values
rs.lock.RUnlock()
b, err := session.EncodeGob(values)
if err != nil {
return
}

View File

@ -20,15 +20,16 @@
//
// Usage:
// import(
//
// _ "github.com/beego/beego/v2/server/web/session/redis_cluster"
// "github.com/beego/beego/v2/server/web/session"
//
// )
//
// func init() {
// globalSessions, _ = session.NewManager("redis_cluster", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070;127.0.0.1:7071"}``)
// go globalSessions.GC()
// }
//
package redis_cluster
import (
@ -100,7 +101,10 @@ func (rs *SessionStore) SessionID(context.Context) string {
// SessionRelease save session values to redis_cluster
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
b, err := session.EncodeGob(rs.values)
rs.lock.RLock()
values := rs.values
rs.lock.RUnlock()
b, err := session.EncodeGob(values)
if err != nil {
return
}

View File

@ -20,8 +20,10 @@
//
// Usage:
// import(
//
// _ "github.com/beego/beego/v2/server/web/session/redis_sentinel"
// "github.com/beego/beego/v2/server/web/session"
//
// )
//
// func init() {
@ -101,7 +103,10 @@ func (rs *SessionStore) SessionID(context.Context) string {
// SessionRelease save session values to redis_sentinel
func (rs *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
b, err := session.EncodeGob(rs.values)
rs.lock.RLock()
values := rs.values
rs.lock.RUnlock()
b, err := session.EncodeGob(values)
if err != nil {
return
}

View File

@ -75,9 +75,11 @@ func (st *CookieSessionStore) SessionID(context.Context) string {
// SessionRelease Write cookie session to http response cookie
func (st *CookieSessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
st.lock.Lock()
encodedCookie, err := encodeCookie(cookiepder.block, cookiepder.config.SecurityKey, cookiepder.config.SecurityName, st.values)
st.lock.Unlock()
st.lock.RLock()
values := st.values
st.lock.RUnlock()
encodedCookie, err := encodeCookie(
cookiepder.block, cookiepder.config.SecurityKey, cookiepder.config.SecurityName, values)
if err == nil {
cookie := &http.Cookie{
Name: cookiepder.config.CookieName,
@ -110,6 +112,7 @@ type CookieProvider struct {
// SessionInit Init cookie session provider with max lifetime and config json.
// maxlifetime is ignored.
// json config:
//
// securityKey - hash string
// blockKey - gob encode hash string. it's saved as aes crypto.
// securityName - recognized name in encoded cookie string

View File

@ -205,7 +205,10 @@ func (s *SessionStore) SessionID(context.Context) string {
// SessionRelease Store the keyvalues into ssdb
func (s *SessionStore) SessionRelease(ctx context.Context, w http.ResponseWriter) {
b, err := session.EncodeGob(s.values)
s.lock.RLock()
values := s.values
s.lock.RUnlock()
b, err := session.EncodeGob(values)
if err != nil {
return
}