Skip to content

[duplicate-code] Duplicate Code Pattern: Label CanFlowTo Iteration in DIFC Labels #1951

@github-actions

Description

@github-actions

Part of duplicate code analysis: #1948

Summary

SecrecyLabel.CanFlowTo and IntegrityLabel.CanFlowTo in internal/difc/labels.go are near-structurally identical: both acquire RLocks on two labels, check for a wildcard tag, then iterate to verify a subset/superset relationship. The checkFlowHelper function already abstracts the CheckFlow method for both types, but CanFlowTo was not unified in the same refactor.

Duplication Details

Pattern: nil-check → dual RLock → wildcard-check → subset/superset loop

  • Severity: Low
  • Occurrences: 2 functions
  • Locations:
    • internal/difc/labels.go lines 173–198 (SecrecyLabel.CanFlowTo, 26 lines)
    • internal/difc/labels.go lines 330–356 (IntegrityLabel.CanFlowTo, 27 lines)

Shared structure:

func (l *XLabel) CanFlowTo(target *XLabel) bool {
    if l == nil || l.Label == nil { return (semantics-specific-nil-return) }
    if target == nil || target.Label == nil { return (semantics-specific-nil-return) }

    l.Label.mu.RLock(); defer l.Label.mu.RUnlock()
    target.Label.mu.RLock(); defer target.Label.mu.RUnlock()

    // Wildcard check (side differs: secrecy checks target; integrity checks l)
    if _, ok := (wildcard-side).Label.tags[WildcardTag]; ok { return true }

    // Subset/superset loop (iteration side differs)
    for tag := range (iter-side).Label.tags {
        if _, ok := (check-side).Label.tags[tag]; !ok { return false }
    }
    return true
}

The only semantic differences are:

  • Which side (l vs target) is the wildcard holder
  • Which side is iterated for the subset/superset check
  • Nil-return value when l == nil

Impact Analysis

  • Maintainability: Adding a new label feature (e.g., negation tags, hierarchical tags) requires updating both CanFlowTo implementations
  • Bug Risk: Low — the locking pattern and loop logic are currently identical, but could diverge in future changes
  • Code Bloat: ~25 lines of parallel logic

Refactoring Recommendations

  1. Extend checkFlowHelper to serve CanFlowTo by calling it from both methods:

    func (l *SecrecyLabel) CanFlowTo(target *SecrecyLabel) bool {
        var srcLabel, targetLabel *Label
        if l != nil { srcLabel = l.Label }
        if target != nil { targetLabel = target.Label }
        ok, _ := checkFlowHelper(srcLabel, targetLabel, true, "Secrecy")
        return ok
    }

    Note: checkFlowHelper already implements the full nil/wildcard/subset/superset logic, making CanFlowTo a trivial wrapper. The only difference is the nil-return value when l == nil for IntegrityLabel (returns target == nil || target.Label.IsEmpty()), which the helper would need to preserve.

    • Estimated effort: 1 hour (plus careful review of nil semantics)
    • Benefits: single locking and iteration path; DIFC correctness bugs fixed in one place
  2. Alternative: Introduce a canFlowHelper boolean variant of checkFlowHelper that directly returns bool without collecting violation tags — useful if the tag-collection overhead of checkFlowHelper is a concern in hot paths.

Implementation Checklist

  • Review duplication findings
  • Verify checkFlowHelper nil semantics match CanFlowTo nil semantics exactly
  • Refactor both CanFlowTo methods to delegate to checkFlowHelper (or a new canFlowHelper)
  • Run DIFC label unit tests (internal/difc/labels_test.go) to confirm correctness

Parent Issue

See parent analysis report: #1948
Related to #1948

Generated by Duplicate Code Detector ·

  • expires on Mar 22, 2026, 3:06 AM UTC

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions