🔍 Duplicate Code Pattern: DIFC Label CheckFlow Implementations
Part of duplicate code analysis: #1719
Summary
SecrecyLabel.CheckFlow and IntegrityLabel.CheckFlow in internal/difc/labels.go share ~32 lines of near-identical structure: nil guard, double RLock, tag-set iteration, and diagnostic logging. The only meaningful difference is the direction of the subset check (secrecy checks source ⊆ target; integrity checks target ⊆ source). This is the largest duplication in the file.
Duplication Details
Pattern: Nil-Guard + Double RLock + Tag Subset Check
-
Severity: High
-
Occurrences: 2 instances
-
Locations:
internal/difc/labels.go (lines ~189–220) — SecrecyLabel.CheckFlow
internal/difc/labels.go (lines ~273–304) — IntegrityLabel.CheckFlow
-
Code Sample:
// SecrecyLabel.CheckFlow — checks source ⊆ target
func (l *SecrecyLabel) CheckFlow(target *SecrecyLabel) (bool, []Tag) {
if l == nil || l.Label == nil {
return true, nil
}
if target == nil || target.Label == nil {
if l.Label.IsEmpty() { return true, nil }
extraTags := l.Label.GetTags()
logLabels.Printf("Secrecy CheckFlow denied: ...")
return false, extraTags
}
l.Label.mu.RLock(); defer l.Label.mu.RUnlock()
target.Label.mu.RLock(); defer target.Label.mu.RUnlock()
var extraTags []Tag
for tag := range l.Label.tags {
if _, ok := target.Label.tags[tag]; !ok {
extraTags = append(extraTags, tag)
}
}
...
return len(extraTags) == 0, extraTags
}
// IntegrityLabel.CheckFlow — checks target ⊆ source (reversed)
func (l *IntegrityLabel) CheckFlow(target *IntegrityLabel) (bool, []Tag) {
if l == nil || l.Label == nil {
if target == nil || target.Label == nil || target.Label.IsEmpty() { return true, nil }
missingTags := target.Label.GetTags()
logLabels.Printf("Integrity CheckFlow denied: ...")
return false, missingTags
}
if target == nil || target.Label == nil { return true, nil }
l.Label.mu.RLock(); defer l.Label.mu.RUnlock()
target.Label.mu.RLock(); defer target.Label.mu.RUnlock()
var missingTags []Tag
for tag := range target.Label.tags { // iterates target, not source
if _, ok := l.Label.tags[tag]; !ok {
missingTags = append(missingTags, tag)
}
}
...
return len(missingTags) == 0, missingTags
}
Impact Analysis
- Maintainability: Fixing a locking bug or adding tracing requires changes in two places
- Bug Risk: The nil-guard ordering already differs slightly between the two — future edits risk further divergence
- Code Bloat: ~32 lines could be shared via a generic subset-check helper
Refactoring Recommendations
-
Extract a private checkLabelSubset helper
// checkLabelSubset checks whether all tags in `haystack` exist in `needleSet`.
// Returns false + the missing/extra tags if the check fails.
func checkLabelSubset(haystack, needleSet *Label, logPrefix string) (bool, []Tag) {
haystack.mu.RLock(); defer haystack.mu.RUnlock()
needleSet.mu.RLock(); defer needleSet.mu.RUnlock()
var missing []Tag
for tag := range haystack.tags {
if _, ok := needleSet.tags[tag]; !ok {
missing = append(missing, tag)
}
}
if len(missing) > 0 {
logLabels.Printf("%s: tags not in target set: %v", logPrefix, missing)
}
return len(missing) == 0, missing
}
Then both CheckFlow methods handle only their specific nil-guard logic and delegate the set comparison.
- Estimated effort: 1 hour (careful with nil guards and test coverage)
- Benefits: Single locking strategy, consistent tag-comparison semantics
-
Alternatively, use Go generics (Go 1.18+) to create a single typed checkFlow[T labelType] function if the type system permits.
Implementation Checklist
Parent Issue
See parent analysis report: #1719
Related to #1719
Generated by Duplicate Code Detector · ◷
🔍 Duplicate Code Pattern: DIFC Label CheckFlow Implementations
Part of duplicate code analysis: #1719
Summary
SecrecyLabel.CheckFlowandIntegrityLabel.CheckFlowininternal/difc/labels.goshare ~32 lines of near-identical structure: nil guard, double RLock, tag-set iteration, and diagnostic logging. The only meaningful difference is the direction of the subset check (secrecy checks source ⊆ target; integrity checks target ⊆ source). This is the largest duplication in the file.Duplication Details
Pattern: Nil-Guard + Double RLock + Tag Subset Check
Severity: High
Occurrences: 2 instances
Locations:
internal/difc/labels.go(lines ~189–220) —SecrecyLabel.CheckFlowinternal/difc/labels.go(lines ~273–304) —IntegrityLabel.CheckFlowCode Sample:
Impact Analysis
Refactoring Recommendations
Extract a private
checkLabelSubsethelperThen both
CheckFlowmethods handle only their specific nil-guard logic and delegate the set comparison.Alternatively, use Go generics (Go 1.18+) to create a single typed
checkFlow[T labelType]function if the type system permits.Implementation Checklist
CheckFlowimplementations side-by-sidecheckLabelSubsetprivate helperCheckFlowmethods to delegatemake test-unitto confirm no regressionsParent Issue
See parent analysis report: #1719
Related to #1719