2022-09-08 15:57:17 +08:00
|
|
|
package internal
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-11-10 21:03:07 +08:00
|
|
|
"fmt"
|
2022-11-21 20:44:02 +08:00
|
|
|
"github.com/antonmedv/expr"
|
|
|
|
"github.com/antonmedv/expr/vm"
|
2022-09-20 04:01:38 +08:00
|
|
|
"github.com/chainreactors/logs"
|
2022-09-08 17:04:41 +08:00
|
|
|
"github.com/chainreactors/spray/pkg"
|
2022-10-26 18:28:40 +08:00
|
|
|
"github.com/chainreactors/spray/pkg/ihttp"
|
2022-09-15 19:27:07 +08:00
|
|
|
"github.com/chainreactors/words"
|
2022-09-08 15:57:17 +08:00
|
|
|
"github.com/panjf2000/ants/v2"
|
2022-09-23 01:20:01 +08:00
|
|
|
"github.com/valyala/fasthttp"
|
2022-11-21 20:44:02 +08:00
|
|
|
"strconv"
|
2022-09-08 15:57:17 +08:00
|
|
|
"sync"
|
2022-09-15 19:27:07 +08:00
|
|
|
"time"
|
2022-09-08 15:57:17 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2022-11-17 17:09:37 +08:00
|
|
|
CheckRedirect func(string) bool
|
2022-09-08 15:57:17 +08:00
|
|
|
)
|
2022-11-17 16:27:44 +08:00
|
|
|
|
2022-11-17 05:40:02 +08:00
|
|
|
var max = 2147483647
|
2022-09-23 01:47:24 +08:00
|
|
|
|
2022-11-10 21:03:07 +08:00
|
|
|
func NewPool(ctx context.Context, config *pkg.Config) (*Pool, error) {
|
2022-09-19 14:42:29 +08:00
|
|
|
pctx, cancel := context.WithCancel(ctx)
|
2022-09-08 15:57:17 +08:00
|
|
|
pool := &Pool{
|
2022-09-23 01:39:00 +08:00
|
|
|
Config: config,
|
2022-11-21 23:56:27 +08:00
|
|
|
Statistor: pkg.NewStatistor(config.BaseURL),
|
2022-09-23 01:39:00 +08:00
|
|
|
ctx: pctx,
|
2022-09-23 01:47:24 +08:00
|
|
|
cancel: cancel,
|
2022-10-26 18:28:40 +08:00
|
|
|
client: ihttp.NewClient(config.Thread, 2, config.ClientType),
|
2022-09-23 01:39:00 +08:00
|
|
|
worder: words.NewWorder(config.Wordlist),
|
2022-11-10 21:03:07 +08:00
|
|
|
baselines: make(map[int]*pkg.Baseline),
|
|
|
|
tempCh: make(chan *pkg.Baseline, config.Thread),
|
2022-09-23 11:20:41 +08:00
|
|
|
wg: sync.WaitGroup{},
|
|
|
|
initwg: sync.WaitGroup{},
|
2022-11-10 17:19:05 +08:00
|
|
|
reqCount: 1,
|
|
|
|
failedCount: 1,
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
switch config.Mod {
|
|
|
|
case pkg.PathSpray:
|
2022-10-26 18:28:40 +08:00
|
|
|
pool.genReq = func(s string) (*ihttp.Request, error) {
|
2022-11-18 20:27:29 +08:00
|
|
|
return ihttp.BuildPathRequest(pool.ClientType, pool.BaseURL, s)
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
2022-10-26 18:28:40 +08:00
|
|
|
pool.check = func() {
|
|
|
|
_ = pool.pool.Invoke(newUnit(pkg.RandPath(), CheckSource))
|
|
|
|
|
2022-11-17 05:40:02 +08:00
|
|
|
if pool.failedCount > pool.BreakThreshold {
|
2022-10-26 18:28:40 +08:00
|
|
|
// 当报错次数超过上限是, 结束任务
|
2022-11-10 21:03:07 +08:00
|
|
|
pool.recover()
|
2022-10-26 18:28:40 +08:00
|
|
|
pool.cancel()
|
|
|
|
}
|
|
|
|
}
|
2022-09-08 15:57:17 +08:00
|
|
|
case pkg.HostSpray:
|
2022-10-26 18:28:40 +08:00
|
|
|
pool.genReq = func(s string) (*ihttp.Request, error) {
|
2022-11-18 20:27:29 +08:00
|
|
|
return ihttp.BuildHostRequest(pool.ClientType, pool.BaseURL, s)
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
2022-10-26 18:28:40 +08:00
|
|
|
|
|
|
|
pool.check = func() {
|
|
|
|
_ = pool.pool.Invoke(newUnit(pkg.RandHost(), CheckSource))
|
|
|
|
|
2022-11-17 05:40:02 +08:00
|
|
|
if pool.failedCount > pool.BreakThreshold {
|
2022-10-26 18:28:40 +08:00
|
|
|
// 当报错次数超过上限是, 结束任务
|
2022-11-10 21:03:07 +08:00
|
|
|
pool.recover()
|
2022-10-26 18:28:40 +08:00
|
|
|
pool.cancel()
|
|
|
|
}
|
|
|
|
}
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
p, _ := ants.NewPoolWithFunc(config.Thread, func(i interface{}) {
|
2022-11-21 23:56:27 +08:00
|
|
|
pool.Statistor.ReqNumber++
|
2022-09-08 15:57:17 +08:00
|
|
|
unit := i.(*Unit)
|
2022-09-20 04:01:38 +08:00
|
|
|
req, err := pool.genReq(unit.path)
|
|
|
|
if err != nil {
|
|
|
|
logs.Log.Error(err.Error())
|
|
|
|
}
|
2022-09-23 01:20:01 +08:00
|
|
|
|
2022-11-10 21:03:07 +08:00
|
|
|
var bl *pkg.Baseline
|
2022-09-23 11:20:41 +08:00
|
|
|
resp, reqerr := pool.client.Do(pctx, req)
|
2022-10-26 18:28:40 +08:00
|
|
|
if pool.ClientType == ihttp.FAST {
|
|
|
|
defer fasthttp.ReleaseResponse(resp.FastResponse)
|
|
|
|
defer fasthttp.ReleaseRequest(req.FastRequest)
|
|
|
|
}
|
|
|
|
|
2022-09-23 11:20:41 +08:00
|
|
|
if reqerr != nil && reqerr != fasthttp.ErrBodyTooLarge {
|
2022-10-19 16:38:23 +08:00
|
|
|
pool.failedCount++
|
2022-11-21 23:56:27 +08:00
|
|
|
pool.Statistor.FailedNumber++
|
2022-11-21 20:44:02 +08:00
|
|
|
bl = &pkg.Baseline{Url: pool.BaseURL + unit.path, IsValid: false, ErrString: reqerr.Error(), Reason: ErrRequestFailed.Error()}
|
2022-11-10 17:19:05 +08:00
|
|
|
pool.failedBaselines = append(pool.failedBaselines, bl)
|
2022-09-08 15:57:17 +08:00
|
|
|
} else {
|
2022-11-21 20:44:02 +08:00
|
|
|
if unit.source != WordSource {
|
2022-11-10 21:03:07 +08:00
|
|
|
bl = pkg.NewBaseline(req.URI(), req.Host(), resp)
|
2022-09-08 15:57:17 +08:00
|
|
|
} else {
|
2022-11-21 20:44:02 +08:00
|
|
|
if unit.source != WordSource || pool.MatchExpr != nil {
|
|
|
|
// 如果非wordsource, 或自定义了match函数, 则所有数据送入tempch中
|
|
|
|
bl = pkg.NewBaseline(req.URI(), req.Host(), resp)
|
|
|
|
} else if err = pool.PreCompare(resp); err == nil {
|
|
|
|
// 通过预对比跳过一些无用数据, 减少性能消耗
|
|
|
|
bl = pkg.NewBaseline(req.URI(), req.Host(), resp)
|
|
|
|
pool.addFuzzyBaseline(bl)
|
|
|
|
} else {
|
|
|
|
bl = pkg.NewInvalidBaseline(req.URI(), req.Host(), resp, err.Error())
|
|
|
|
}
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch unit.source {
|
2022-11-17 05:48:46 +08:00
|
|
|
case InitRandomSource:
|
2022-10-27 23:40:15 +08:00
|
|
|
pool.base = bl
|
2022-11-10 21:03:07 +08:00
|
|
|
pool.addFuzzyBaseline(bl)
|
2022-10-27 23:40:15 +08:00
|
|
|
pool.initwg.Done()
|
|
|
|
return
|
2022-11-17 05:48:46 +08:00
|
|
|
case InitIndexSource:
|
|
|
|
pool.index = bl
|
|
|
|
pool.initwg.Done()
|
|
|
|
return
|
2022-09-20 18:09:06 +08:00
|
|
|
case CheckSource:
|
2022-11-21 20:44:02 +08:00
|
|
|
if bl.ErrString != "" {
|
|
|
|
logs.Log.Warnf("[check.error] maybe ip had banned by waf, break (%d/%d), error: %s", pool.failedCount, pool.BreakThreshold, bl.ErrString)
|
2022-11-10 15:43:25 +08:00
|
|
|
pool.failedBaselines = append(pool.failedBaselines, bl)
|
2022-11-10 17:32:58 +08:00
|
|
|
} else if i := pool.base.Compare(bl); i < 1 {
|
|
|
|
if i == 0 {
|
|
|
|
logs.Log.Debug("[check.fuzzy] maybe trigger risk control, " + bl.String())
|
|
|
|
} else {
|
|
|
|
logs.Log.Warn("[check.failed] maybe trigger risk control, " + bl.String())
|
|
|
|
}
|
|
|
|
|
2022-11-10 15:43:25 +08:00
|
|
|
pool.failedBaselines = append(pool.failedBaselines, bl)
|
|
|
|
} else {
|
2022-11-10 21:03:07 +08:00
|
|
|
pool.resetFailed() // 如果后续访问正常, 重置错误次数
|
2022-11-10 15:43:25 +08:00
|
|
|
logs.Log.Debug("[check.pass] " + bl.String())
|
2022-09-23 01:39:00 +08:00
|
|
|
}
|
|
|
|
|
2022-09-08 15:57:17 +08:00
|
|
|
case WordSource:
|
2022-09-23 01:20:01 +08:00
|
|
|
// 异步进行性能消耗较大的深度对比
|
|
|
|
pool.tempCh <- bl
|
2022-11-11 10:37:30 +08:00
|
|
|
pool.reqCount++
|
2022-11-17 05:40:02 +08:00
|
|
|
if pool.reqCount%pool.CheckPeriod == 0 {
|
2022-11-11 10:20:32 +08:00
|
|
|
pool.reqCount++
|
2022-11-21 23:56:27 +08:00
|
|
|
pool.Statistor.CheckNumber++
|
2022-09-23 11:20:41 +08:00
|
|
|
go pool.check()
|
2022-11-17 05:40:02 +08:00
|
|
|
} else if pool.failedCount%pool.ErrPeriod == 0 {
|
2022-11-11 10:20:32 +08:00
|
|
|
pool.failedCount++
|
2022-11-21 23:56:27 +08:00
|
|
|
pool.Statistor.CheckNumber++
|
2022-09-23 11:20:41 +08:00
|
|
|
go pool.check()
|
|
|
|
}
|
2022-11-10 15:43:25 +08:00
|
|
|
pool.bar.Done()
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
2022-10-19 16:38:23 +08:00
|
|
|
|
2022-09-08 15:57:17 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
pool.pool = p
|
2022-11-11 10:20:32 +08:00
|
|
|
go func() {
|
|
|
|
for bl := range pool.tempCh {
|
2022-11-23 10:59:15 +08:00
|
|
|
if _, ok := pool.Statistor.Counts[bl.Status]; ok {
|
|
|
|
pool.Statistor.Counts[bl.Status]++
|
|
|
|
} else {
|
|
|
|
pool.Statistor.Counts[bl.Status] = 1
|
|
|
|
}
|
2022-11-21 20:44:02 +08:00
|
|
|
var status bool
|
|
|
|
if pool.MatchExpr != nil {
|
|
|
|
if pool.CompareWithExpr(pool.MatchExpr, bl) {
|
|
|
|
status = true
|
2022-11-11 10:20:32 +08:00
|
|
|
}
|
|
|
|
} else {
|
2022-11-21 20:44:02 +08:00
|
|
|
if pool.BaseCompare(bl) {
|
|
|
|
status = true
|
|
|
|
}
|
2022-11-11 10:20:32 +08:00
|
|
|
}
|
2022-11-21 20:44:02 +08:00
|
|
|
|
|
|
|
if status {
|
2022-11-21 23:56:27 +08:00
|
|
|
pool.Statistor.FoundNumber++
|
2022-11-21 20:44:02 +08:00
|
|
|
if pool.FilterExpr != nil && pool.CompareWithExpr(pool.FilterExpr, bl) {
|
2022-11-21 23:56:27 +08:00
|
|
|
pool.Statistor.FilteredNumber++
|
2022-11-21 20:44:02 +08:00
|
|
|
bl.Reason = ErrCustomFilter.Error()
|
|
|
|
bl.IsValid = false
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bl.IsValid = false
|
|
|
|
}
|
|
|
|
pool.OutputCh <- bl
|
|
|
|
pool.wg.Done()
|
2022-11-11 10:20:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pool.analyzeDone = true
|
|
|
|
}()
|
2022-09-08 15:57:17 +08:00
|
|
|
return pool, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type Pool struct {
|
|
|
|
*pkg.Config
|
2022-11-21 23:56:27 +08:00
|
|
|
Statistor *pkg.Statistor
|
2022-11-10 21:03:07 +08:00
|
|
|
client *ihttp.Client
|
|
|
|
pool *ants.PoolWithFunc
|
|
|
|
bar *pkg.Bar
|
|
|
|
ctx context.Context
|
|
|
|
cancel context.CancelFunc
|
|
|
|
tempCh chan *pkg.Baseline // 待处理的baseline
|
2022-11-10 15:43:25 +08:00
|
|
|
reqCount int
|
|
|
|
failedCount int
|
2022-11-10 21:03:07 +08:00
|
|
|
failedBaselines []*pkg.Baseline
|
|
|
|
base *pkg.Baseline
|
2022-11-17 05:48:46 +08:00
|
|
|
index *pkg.Baseline
|
2022-11-10 21:03:07 +08:00
|
|
|
baselines map[int]*pkg.Baseline
|
2022-11-10 15:43:25 +08:00
|
|
|
analyzeDone bool
|
|
|
|
genReq func(s string) (*ihttp.Request, error)
|
|
|
|
check func()
|
|
|
|
worder *words.Worder
|
|
|
|
wg sync.WaitGroup
|
|
|
|
initwg sync.WaitGroup // 初始化用, 之后改成锁
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
|
|
|
|
2022-09-23 01:39:00 +08:00
|
|
|
func (p *Pool) Init() error {
|
2022-11-17 05:48:46 +08:00
|
|
|
p.initwg.Add(2)
|
|
|
|
p.pool.Invoke(newUnit(pkg.RandPath(), InitRandomSource))
|
|
|
|
p.pool.Invoke(newUnit("/", InitIndexSource))
|
2022-09-23 11:20:41 +08:00
|
|
|
p.initwg.Wait()
|
2022-09-08 15:57:17 +08:00
|
|
|
// todo 分析baseline
|
|
|
|
// 检测基本访问能力
|
|
|
|
|
2022-11-21 20:44:02 +08:00
|
|
|
if p.base.ErrString != "" {
|
2022-11-10 21:03:07 +08:00
|
|
|
return fmt.Errorf(p.base.String())
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
|
|
|
|
2022-11-21 20:44:02 +08:00
|
|
|
if p.index.ErrString != "" {
|
2022-11-17 05:48:46 +08:00
|
|
|
return fmt.Errorf(p.index.String())
|
|
|
|
}
|
|
|
|
|
2022-09-23 11:20:41 +08:00
|
|
|
p.base.Collect()
|
2022-11-17 05:48:46 +08:00
|
|
|
p.index.Collect()
|
|
|
|
|
|
|
|
logs.Log.Important("[baseline.random] " + p.base.String())
|
2022-11-17 16:27:44 +08:00
|
|
|
logs.Log.Important("[baseline.index] " + p.index.String())
|
2022-11-17 05:48:46 +08:00
|
|
|
|
2022-09-23 11:20:41 +08:00
|
|
|
if p.base.RedirectURL != "" {
|
2022-09-23 01:20:01 +08:00
|
|
|
CheckRedirect = func(redirectURL string) bool {
|
2022-09-23 11:20:41 +08:00
|
|
|
if redirectURL == p.base.RedirectURL {
|
2022-09-08 15:57:17 +08:00
|
|
|
// 相同的RedirectURL将被认为是无效数据
|
|
|
|
return false
|
2022-09-23 01:20:01 +08:00
|
|
|
} else {
|
|
|
|
// path为3xx, 且与baseline中的RedirectURL不同时, 为有效数据
|
|
|
|
return true
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-11-10 15:48:38 +08:00
|
|
|
func (p *Pool) Run(ctx context.Context, offset, limit int) {
|
2022-11-21 23:56:27 +08:00
|
|
|
p.Statistor.Offset = offset
|
2022-09-15 19:27:07 +08:00
|
|
|
Loop:
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case u, ok := <-p.worder.C:
|
|
|
|
if !ok {
|
|
|
|
break Loop
|
|
|
|
}
|
2022-11-21 23:56:27 +08:00
|
|
|
p.Statistor.End++
|
2022-11-10 15:48:38 +08:00
|
|
|
if p.reqCount < offset {
|
|
|
|
p.reqCount++
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-11-21 23:56:27 +08:00
|
|
|
if p.Statistor.End > limit {
|
2022-11-10 15:48:38 +08:00
|
|
|
break Loop
|
|
|
|
}
|
|
|
|
|
2022-11-10 04:22:42 +08:00
|
|
|
for _, fn := range p.Fns {
|
|
|
|
u = fn(u)
|
|
|
|
}
|
2022-11-10 04:48:07 +08:00
|
|
|
if u == "" {
|
|
|
|
continue
|
|
|
|
}
|
2022-09-20 04:01:38 +08:00
|
|
|
p.wg.Add(1)
|
|
|
|
_ = p.pool.Invoke(newUnit(u, WordSource))
|
2022-09-15 19:27:07 +08:00
|
|
|
case <-ctx.Done():
|
|
|
|
break Loop
|
2022-09-19 14:42:29 +08:00
|
|
|
case <-p.ctx.Done():
|
|
|
|
break Loop
|
2022-09-15 19:27:07 +08:00
|
|
|
}
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
2022-11-11 14:50:59 +08:00
|
|
|
p.wg.Wait()
|
2022-11-21 23:56:27 +08:00
|
|
|
p.Statistor.ReqNumber = p.reqCount
|
2022-09-23 11:20:41 +08:00
|
|
|
p.Close()
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:28:40 +08:00
|
|
|
func (p *Pool) PreCompare(resp *ihttp.Response) error {
|
2022-11-17 16:27:44 +08:00
|
|
|
status := resp.StatusCode()
|
2022-11-17 17:09:37 +08:00
|
|
|
if IntsContains(WhiteStatus, status) {
|
|
|
|
// 如果为白名单状态码则直接返回
|
|
|
|
return nil
|
|
|
|
}
|
2022-11-17 16:27:44 +08:00
|
|
|
if p.base != nil && p.base.Status != 200 && p.base.Status == status {
|
2022-11-10 21:03:07 +08:00
|
|
|
return ErrSameStatus
|
|
|
|
}
|
|
|
|
|
2022-11-17 17:09:37 +08:00
|
|
|
if IntsContains(BlackStatus, status) {
|
2022-09-15 19:27:07 +08:00
|
|
|
return ErrBadStatus
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
|
|
|
|
2022-11-17 17:09:37 +08:00
|
|
|
if IntsContains(WAFStatus, status) {
|
2022-11-17 16:27:44 +08:00
|
|
|
return ErrWaf
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
|
|
|
|
2022-11-17 16:27:44 +08:00
|
|
|
if CheckRedirect != nil && !CheckRedirect(string(resp.GetHeader("Location"))) {
|
|
|
|
return ErrRedirect
|
2022-09-26 17:19:08 +08:00
|
|
|
}
|
2022-09-08 15:57:17 +08:00
|
|
|
|
2022-09-15 19:27:07 +08:00
|
|
|
return nil
|
2022-09-08 15:57:17 +08:00
|
|
|
}
|
|
|
|
|
2022-11-21 20:44:02 +08:00
|
|
|
func (p *Pool) BaseCompare(bl *pkg.Baseline) bool {
|
2022-11-11 10:20:32 +08:00
|
|
|
if !bl.IsValid {
|
|
|
|
// precompare 确认无效数据直接送入管道
|
|
|
|
p.OutputCh <- bl
|
2022-11-21 20:44:02 +08:00
|
|
|
return false
|
2022-11-11 10:20:32 +08:00
|
|
|
}
|
2022-11-11 11:55:49 +08:00
|
|
|
var status = -1
|
|
|
|
base, ok := p.baselines[bl.Status] // 挑选对应状态码的baseline进行compare
|
2022-11-17 05:48:46 +08:00
|
|
|
if !ok {
|
|
|
|
if p.base.Status == bl.Status {
|
|
|
|
// 当other的状态码与base相同时, 会使用base
|
|
|
|
ok = true
|
|
|
|
base = p.base
|
|
|
|
} else if p.index.Status == bl.Status {
|
|
|
|
// 当other的状态码与index相同时, 会使用index
|
|
|
|
ok = true
|
|
|
|
base = p.index
|
|
|
|
}
|
2022-11-11 11:40:53 +08:00
|
|
|
}
|
|
|
|
|
2022-11-11 11:55:49 +08:00
|
|
|
if ok {
|
|
|
|
if status = base.Compare(bl); status == 1 {
|
2022-11-21 20:44:02 +08:00
|
|
|
bl.Reason = ErrCompareFailed.Error()
|
|
|
|
return false
|
2022-09-23 01:20:01 +08:00
|
|
|
}
|
2022-11-11 10:20:32 +08:00
|
|
|
}
|
2022-09-23 01:20:01 +08:00
|
|
|
|
2022-11-11 14:50:59 +08:00
|
|
|
bl.Collect()
|
|
|
|
for _, f := range bl.Frameworks {
|
|
|
|
if f.Tag == "waf/cdn" {
|
2022-11-21 23:56:27 +08:00
|
|
|
p.Statistor.WafedNumber++
|
2022-11-21 20:44:02 +08:00
|
|
|
bl.Reason = ErrWaf.Error()
|
|
|
|
return false
|
2022-11-11 11:55:49 +08:00
|
|
|
}
|
2022-09-20 04:01:38 +08:00
|
|
|
}
|
2022-09-23 11:20:41 +08:00
|
|
|
|
2022-11-11 14:50:59 +08:00
|
|
|
if ok && status == 0 && base.FuzzyCompare(bl) {
|
2022-11-21 23:56:27 +08:00
|
|
|
p.Statistor.FuzzyNumber++
|
2022-11-21 20:44:02 +08:00
|
|
|
bl.Reason = ErrFuzzyCompareFailed.Error()
|
2022-11-11 14:50:59 +08:00
|
|
|
p.PutToFuzzy(bl)
|
2022-11-21 20:44:02 +08:00
|
|
|
return false
|
2022-11-11 14:50:59 +08:00
|
|
|
}
|
|
|
|
|
2022-11-21 20:44:02 +08:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Pool) CompareWithExpr(exp *vm.Program, other *pkg.Baseline) bool {
|
|
|
|
params := map[string]interface{}{
|
|
|
|
"index": p.index,
|
|
|
|
"base": p.base,
|
|
|
|
"current": other,
|
|
|
|
}
|
|
|
|
for _, status := range FuzzyStatus {
|
|
|
|
if bl, ok := p.baselines[status]; ok {
|
|
|
|
params["bl"+strconv.Itoa(status)] = bl
|
|
|
|
} else {
|
|
|
|
params["bl"+strconv.Itoa(status)] = &pkg.Baseline{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err := expr.Run(exp, params)
|
|
|
|
if err != nil {
|
|
|
|
logs.Log.Warn(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
if res == true {
|
|
|
|
return true
|
|
|
|
} else {
|
|
|
|
return false
|
|
|
|
}
|
2022-09-23 01:20:01 +08:00
|
|
|
}
|
2022-09-26 17:19:08 +08:00
|
|
|
|
2022-11-10 21:03:07 +08:00
|
|
|
func (p *Pool) addFuzzyBaseline(bl *pkg.Baseline) {
|
2022-11-11 01:14:07 +08:00
|
|
|
if _, ok := p.baselines[bl.Status]; !ok && IntsContains(FuzzyStatus, bl.Status) {
|
2022-11-10 21:03:07 +08:00
|
|
|
bl.Collect()
|
|
|
|
p.baselines[bl.Status] = bl
|
|
|
|
logs.Log.Importantf("[baseline.%dinit] %s", bl.Status, bl.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-10 21:18:26 +08:00
|
|
|
func (p *Pool) PutToInvalid(bl *pkg.Baseline, reason string) {
|
|
|
|
bl.IsValid = false
|
2022-11-11 10:20:32 +08:00
|
|
|
p.OutputCh <- bl
|
2022-11-10 21:18:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Pool) PutToFuzzy(bl *pkg.Baseline) {
|
|
|
|
bl.IsFuzzy = true
|
2022-11-11 10:20:32 +08:00
|
|
|
p.FuzzyCh <- bl
|
2022-11-10 21:18:26 +08:00
|
|
|
}
|
|
|
|
|
2022-11-10 21:03:07 +08:00
|
|
|
func (p *Pool) resetFailed() {
|
2022-11-11 10:37:30 +08:00
|
|
|
p.failedCount = 1
|
2022-11-10 15:43:25 +08:00
|
|
|
p.failedBaselines = nil
|
|
|
|
}
|
|
|
|
|
2022-11-10 21:03:07 +08:00
|
|
|
func (p *Pool) recover() {
|
2022-11-10 15:43:25 +08:00
|
|
|
logs.Log.Errorf("failed request exceeds the threshold , task will exit. Breakpoint %d", p.reqCount)
|
|
|
|
logs.Log.Error("collecting failed check")
|
2022-11-10 17:19:05 +08:00
|
|
|
for i, bl := range p.failedBaselines {
|
|
|
|
logs.Log.Errorf("[failed.%d] %s", i, bl.String())
|
2022-11-10 15:43:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-23 11:20:41 +08:00
|
|
|
func (p *Pool) Close() {
|
2022-11-17 16:58:14 +08:00
|
|
|
for p.analyzeDone {
|
2022-09-23 11:20:41 +08:00
|
|
|
time.Sleep(time.Duration(100) * time.Millisecond)
|
|
|
|
}
|
2022-11-11 14:50:59 +08:00
|
|
|
close(p.tempCh)
|
|
|
|
p.bar.Close()
|
2022-09-23 11:20:41 +08:00
|
|
|
}
|