Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions analyzer/analyzer.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
// Package analyzer provides an interface for analyzing source code for compatibility issues.
package analyzer

import (
"crypto/sha256"
"encoding/hex"
)

// Analyzer represents the interface for the analyzer.
type Analyzer interface {
// Analyze analyzes the provided source code and returns any issues found.
Expand All @@ -26,6 +31,17 @@ type Issue struct {
Severity IssueSeverity `json:"severity"`
Impact string `json:"impact,omitempty"`
Reference string `json:"reference,omitempty"`
Hash string `json:"hash,omitempty"`
}

func (i *Issue) CalculateHash() {
hashString := i.Message
if i.CallStack != nil {
hashString = hashString + "::" + i.CallStack.getHashString()
}
h := sha256.New()
h.Write([]byte(hashString))
i.Hash = hex.EncodeToString(h.Sum(nil))
}

// CallStack represents a location in the code where the issue originates.
Expand All @@ -37,6 +53,14 @@ type CallStack struct {
CallStack *CallStack `json:"callStack,omitempty"` // The trace of calls leading to this source.
}

func (src *CallStack) getHashString() string {
hashString := src.Function
if src.CallStack != nil {
hashString = hashString + "<-" + src.CallStack.getHashString()
}
return hashString
}

// Copy creates a deep copy of the CallStack.
func (src *CallStack) Copy() *CallStack {
if src == nil {
Expand Down
1 change: 1 addition & 0 deletions analyzer/opcode/opcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func (op *opcode) Analyze(path string, withTrace bool) ([]*analyzer.Issue, error
if !withTrace {
source.CallStack = nil
}
issue.CalculateHash()
issues = append(issues, issue)
}
}
Expand Down
7 changes: 5 additions & 2 deletions analyzer/syscall/asm_syscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,16 @@ func (a *asmSyscallAnalyser) Analyze(path string, withTrace bool) ([]*analyzer.I
if !withTrace {
source.CallStack = nil
}
issues = append(issues, &analyzer.Issue{

issue := &analyzer.Issue{
Severity: severity,
Message: message,
CallStack: source,
Impact: potentialImpactMsg,
Reference: analyzerWorkingPrincipalURL,
})
}
issue.CalculateHash()
issues = append(issues, issue)
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions analyzer/syscall/go_syscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@ func (a *goSyscallAnalyser) Analyze(path string, withTrace bool) ([]*analyzer.Is
message = fmt.Sprintf("Potential NOOP Syscall Detected: %d", syscll.num)
}

issues = append(issues, &analyzer.Issue{
issue := &analyzer.Issue{
Severity: severity,
CallStack: stackTrace,
Message: message,
})
}
issue.CalculateHash()
issues = append(issues, issue)
}

return issues, nil
Expand Down
9 changes: 9 additions & 0 deletions renderer/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package renderer
import (
"encoding/json"
"io"
"sort"

"github.com/ChainSafe/vm-compat/analyzer"
)
Expand All @@ -16,6 +17,14 @@ func NewJSONRenderer() Renderer {
}

func (r *JSONRenderer) Render(issues []*analyzer.Issue, output io.Writer) error {
sort.Slice(issues, func(i, j int) bool {
// Sort by severity first
if issues[i].Severity != issues[j].Severity {
return issues[i].Severity < issues[j].Severity
}
// If severity is the same, sort by hash lexicographically
return issues[i].Hash < issues[j].Hash
})
return json.NewEncoder(output).Encode(issues)
}

Expand Down
Loading