package detect // Location represents a location in a file type Location struct { startLine int endLine int startColumn int endColumn int startLineIndex int endLineIndex int } func location(newlineIndices [][]int, raw string, matchIndex []int) Location { var ( prevNewLine int location Location lineSet bool _lineNum int ) start := matchIndex[0] end := matchIndex[1] // default startLineIndex to 0 location.startLineIndex = 0 // Fixes: https://github.com/zricethezav/gitleaks/issues/1037 // When a fragment does NOT have any newlines, a default "newline" // will be counted to make the subsequent location calculation logic work // for fragments will no newlines. if len(newlineIndices) == 0 { newlineIndices = [][]int{ {len(raw), len(raw) + 1}, } } for lineNum, pair := range newlineIndices { _lineNum = lineNum newLineByteIndex := pair[0] if prevNewLine <= start && start < newLineByteIndex { lineSet = true location.startLine = lineNum location.endLine = lineNum location.startColumn = (start - prevNewLine) + 1 // +1 because counting starts at 1 location.startLineIndex = prevNewLine location.endLineIndex = newLineByteIndex } if prevNewLine < end && end <= newLineByteIndex { location.endLine = lineNum location.endColumn = (end - prevNewLine) location.endLineIndex = newLineByteIndex } prevNewLine = pair[0] } if !lineSet { // if lines never get set then that means the secret is most likely // on the last line of the diff output and the diff output does not have // a newline location.startColumn = (start - prevNewLine) + 1 // +1 because counting starts at 1 location.endColumn = (end - prevNewLine) location.startLine = _lineNum + 1 location.endLine = _lineNum + 1 // search for new line byte index i := 0 for end+i < len(raw) { if raw[end+i] == '\n' { break } if raw[end+i] == '\r' { break } i++ } location.endLineIndex = end + i } return location }