Skip to content

Commit 0f81e43

Browse files
fix: use line relative to file instead of relative to chunk (#291)
**Proposed Changes** - Fixed start and end line of secret when chunking is used - Instead of calculating the line taking into account only the chunk, it also considers the context of the file. At the moment, we use context variables to pass on information about the lines in the chunks, **but this is a temporary solution until the engine instance is restructured**. **Checklist** - [ ] I covered my changes with tests. - [ ] I Updated the documentation that is affected by my changes: - [ ] Change in the CLI arguments - [ ] Change in the configuration file
1 parent 88c8dc4 commit 0f81e43

3 files changed

Lines changed: 34 additions & 15 deletions

File tree

engine/chunk/chunk.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ func (c *Chunk) PutBuf(window *bytes.Buffer) {
106106
// GetPeekedBuf returns a fixed-size []byte from the pool
107107
func (c *Chunk) GetPeekedBuf() (*[]byte, bool) {
108108
b, ok := c.peekedBufPool.Get().(*[]byte)
109+
if !ok {
110+
return nil, false
111+
}
112+
// reslice to its full capacity so Read can fill it
113+
*b = (*b)[:cap(*b)]
109114
return b, ok
110115
}
111116

engine/engine.go

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,13 @@ type IEngine interface {
5151
GetRuleBaseRiskScore(ruleId string) float64
5252
}
5353

54+
type ctxKey string
55+
5456
const (
55-
customRegexRuleIdFormat = "custom-regex-%d"
56-
CxFileEndMarker = ";cx-file-end"
57+
customRegexRuleIdFormat = "custom-regex-%d"
58+
CxFileEndMarker = ";cx-file-end"
59+
totalLinesKey ctxKey = "totalLines"
60+
linesInChunkKey ctxKey = "linesInChunk"
5761
)
5862

5963
type EngineConfig struct {
@@ -109,7 +113,7 @@ func (e *Engine) DetectFragment(item plugins.ISourceItem, secretsChannel chan *s
109113
FilePath: item.GetSource(),
110114
}
111115

112-
return e.detectSecrets(item, fragment, secretsChannel, pluginName)
116+
return e.detectSecrets(context.Background(), item, fragment, secretsChannel, pluginName)
113117
}
114118

115119
// DetectFile reads the given file and detects secrets in it
@@ -137,7 +141,7 @@ func (e *Engine) DetectFile(ctx context.Context, item plugins.ISourceItem, secre
137141
}
138142
defer e.semaphore.ReleaseMemoryWeight(weight)
139143

140-
return e.detectChunks(item, secretsChannel)
144+
return e.detectChunks(ctx, item, secretsChannel)
141145
}
142146
// fileSize * 2 -> data file bytes and its conversion to string
143147
weight := fileSize * 2
@@ -156,11 +160,11 @@ func (e *Engine) DetectFile(ctx context.Context, item plugins.ISourceItem, secre
156160
FilePath: item.GetSource(),
157161
}
158162

159-
return e.detectSecrets(item, fragment, secretsChannel, "filesystem")
163+
return e.detectSecrets(ctx, item, fragment, secretsChannel, "filesystem")
160164
}
161165

162166
// detectChunks reads the given file in chunks and detects secrets in each chunk
163-
func (e *Engine) detectChunks(item plugins.ISourceItem, secretsChannel chan *secrets.Secret) error {
167+
func (e *Engine) detectChunks(ctx context.Context, item plugins.ISourceItem, secretsChannel chan *secrets.Secret) error {
164168
f, err := os.Open(item.GetSource())
165169
if err != nil {
166170
return fmt.Errorf("failed to open file %s: %w", item.GetSource(), err)
@@ -194,20 +198,22 @@ func (e *Engine) detectChunks(item plugins.ISourceItem, secretsChannel chan *sec
194198
Raw: chunkStr,
195199
FilePath: item.GetSource(),
196200
}
197-
if detectErr := e.detectSecrets(item, fragment, secretsChannel, "filesystem"); detectErr != nil {
201+
ctx = context.WithValue(ctx, totalLinesKey, totalLines)
202+
ctx = context.WithValue(ctx, linesInChunkKey, linesInChunk)
203+
if detectErr := e.detectSecrets(ctx, item, fragment, secretsChannel, "filesystem"); detectErr != nil {
198204
return fmt.Errorf("failed to detect secrets: %w", detectErr)
199205
}
200206
}
201207
}
202208

203209
// detectSecrets detects secrets and sends them to the secrets channel
204-
func (e *Engine) detectSecrets(item plugins.ISourceItem, fragment detect.Fragment, secrets chan *secrets.Secret,
210+
func (e *Engine) detectSecrets(ctx context.Context, item plugins.ISourceItem, fragment detect.Fragment, secrets chan *secrets.Secret,
205211
pluginName string) error {
206212
fragment.Raw += CxFileEndMarker + "\n"
207213

208214
values := e.detector.Detect(fragment)
209215
for _, value := range values {
210-
secret, buildErr := buildSecret(item, value, pluginName)
216+
secret, buildErr := buildSecret(ctx, item, value, pluginName)
211217
if buildErr != nil {
212218
return fmt.Errorf("failed to build secret: %w", buildErr)
213219
}
@@ -306,10 +312,10 @@ func GetRulesCommand(engineConfig *EngineConfig) *cobra.Command {
306312
}
307313

308314
// buildSecret creates a secret object from the given source item and finding
309-
func buildSecret(item plugins.ISourceItem, value report.Finding, pluginName string) (*secrets.Secret, error) {
315+
func buildSecret(ctx context.Context, item plugins.ISourceItem, value report.Finding, pluginName string) (*secrets.Secret, error) {
310316
gitInfo := item.GetGitInfo()
311317
itemId := getFindingId(item, value)
312-
startLine, endLine, err := getStartAndEndLines(pluginName, gitInfo, value)
318+
startLine, endLine, err := getStartAndEndLines(ctx, pluginName, gitInfo, value)
313319
if err != nil {
314320
return nil, fmt.Errorf("failed to get start and end lines for source %s: %w", item.GetSource(), err)
315321
}
@@ -342,13 +348,21 @@ func getFindingId(item plugins.ISourceItem, finding report.Finding) string {
342348
return fmt.Sprintf("%x", sha)
343349
}
344350

345-
func getStartAndEndLines(pluginName string, gitInfo *plugins.GitInfo, value report.Finding) (int, int, error) {
351+
func getStartAndEndLines(ctx context.Context, pluginName string, gitInfo *plugins.GitInfo, value report.Finding) (int, int, error) {
346352
var startLine, endLine int
347353
var err error
348354

349355
if pluginName == "filesystem" {
350-
startLine = value.StartLine + 1
351-
endLine = value.EndLine + 1
356+
totalLines, totalOK := ctx.Value(totalLinesKey).(int)
357+
chunkLines, chunkOK := ctx.Value(linesInChunkKey).(int)
358+
359+
offset := 1
360+
if totalOK && chunkOK {
361+
offset = (totalLines - chunkLines) + 1
362+
}
363+
364+
startLine = value.StartLine + offset
365+
endLine = value.EndLine + offset
352366
} else if pluginName == "git" {
353367
startLine, endLine, err = plugins.GetGitStartAndEndLine(gitInfo, value.StartLine, value.EndLine)
354368
if err != nil {

engine/engine_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ func TestDetectChunks(t *testing.T) {
423423
tmp := t.TempDir()
424424
src := tc.makeFile(tmp)
425425

426-
err := engine.detectChunks(&item{source: src}, make(chan *secrets.Secret, 1))
426+
err := engine.detectChunks(context.Background(), &item{source: src}, make(chan *secrets.Secret, 1))
427427
loggedMessage := logsBuffer.String()
428428
if tc.expectedErr != nil {
429429
require.ErrorContains(t, err, tc.expectedErr.Error())

0 commit comments

Comments
 (0)