Skip to content

Use non-optional UUID init for zero-IDFA sentinel#472

Closed
yusuftor wants to merge 1 commit into
developfrom
fix-zero-idfa-uuid-comparison
Closed

Use non-optional UUID init for zero-IDFA sentinel#472
yusuftor wants to merge 1 commit into
developfrom
fix-zero-idfa-uuid-comparison

Conversation

@yusuftor
Copy link
Copy Markdown
Collaborator

@yusuftor yusuftor commented May 14, 2026

Summary

Follow-up to #470. The reviewer flagged that private static let zeroAdvertisingIdentifier = UUID(uuidString: "...") types the constant as UUID? — if the literal ever failed to parse (impossible for this constant, but the type allows it), the equality check at the call site would be nil != identifierValue → false and the zero-IDFA would slip through unfiltered.

UUID has a non-optional init(uuid: uuid_t) that takes the 16-byte tuple directly. Switching to that removes the optionality without needing a force-unwrap.

Test plan

  • swiftlint clean
  • Build passes

🤖 Generated with Claude Code

Greptile Summary

This PR swaps the zero-IDFA sentinel constant from UUID(uuidString:) (which produces UUID?) to UUID(uuid:) with a 16-byte all-zero tuple (which produces a non-optional UUID), closing a theoretical type-safety gap introduced in PR #470.

  • The sentinel zeroAdvertisingIdentifier is now typed as UUID rather than UUID?, so the == comparison against identifierValue is unambiguous and can never silently evaluate to false due to a nil optional.
  • The new comment in the file mis-labels the failure mode as "false-positive" when it is actually a false-negative (the filter fails to catch the zero IDFA); the code change itself is correct.

Confidence Score: 5/5

Safe to merge — the one-line constant change correctly removes optionality from the zero-IDFA sentinel, and the only finding is a word choice error in the explanatory comment.

The fix is minimal, targeted, and mechanically correct: UUID(uuid:) with all-zero bytes produces the same value as the old string literal but as a non-optional type, so the equality check is now unconditionally well-typed. The only thing flagged is that the comment describes the failure mode as a 'false-positive' when it is actually a false-negative.

No files require special attention.

Important Files Changed

Filename Overview
Sources/SuperwallKit/Analytics/Attribution/AttributionFetcher.swift Replaces UUID(uuidString:) (returns UUID?) with UUID(uuid:) (returns UUID) for the zero-IDFA sentinel constant, eliminating the optionality and making the equality check unconditionally correct. Only issue is a minor terminology error in the new comment.

Sequence Diagram

sequenceDiagram
    participant Caller
    participant AttributionFetcher
    participant ASIdentifierManager

    Caller->>AttributionFetcher: identifierForAdvertisers
    AttributionFetcher->>ASIdentifierManager: adsIdentifier
    ASIdentifierManager-->>AttributionFetcher: UUID? (nil or value)
    alt adsIdentifier is nil
        AttributionFetcher-->>Caller: nil
    else adsIdentifier is UUID
        AttributionFetcher->>AttributionFetcher: "identifierValue == zeroAdvertisingIdentifier (UUID == UUID, always valid)"
        alt identifierValue is all-zeros sentinel
            AttributionFetcher-->>Caller: nil (filtered)
        else identifierValue is real IDFA
            AttributionFetcher-->>Caller: identifierValue.uuidString
        end
    end
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
Sources/SuperwallKit/Analytics/Attribution/AttributionFetcher.swift:59-61
The comment says "silently false-positive" but the failure mode is a false-negative: if `zeroAdvertisingIdentifier` were `nil`, the equality check would return `false`, the `if` block would not fire, and the all-zeros IDFA would pass through unfiltered — the opposite of a false-positive.

```suggestion
  // Non-optional construction via `init(uuid:)` — `init(uuidString:)` returns
  // an Optional which would make the equality check silently false-negative
  // (zero-IDFA passes through unfiltered) if the literal ever failed to parse.
```

Reviews (1): Last reviewed commit: "Use non-optional UUID init for zero-IDFA..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

UUID(uuidString:) returns Optional, which would silently make the
equality check at the call site false if the literal ever failed to
parse — the zero-IDFA sentinel would then slip through unfiltered.
Switch to UUID(uuid:) which takes the 16-byte tuple directly and
returns a non-optional, removing the optionality from the comparison
without resorting to force-unwrap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment on lines +59 to +61
// Non-optional construction via `init(uuid:)` — `init(uuidString:)` returns
// an Optional which would make the equality check silently false-positive
// if the literal ever failed to parse.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The comment says "silently false-positive" but the failure mode is a false-negative: if zeroAdvertisingIdentifier were nil, the equality check would return false, the if block would not fire, and the all-zeros IDFA would pass through unfiltered — the opposite of a false-positive.

Suggested change
// Non-optional construction via `init(uuid:)` — `init(uuidString:)` returns
// an Optional which would make the equality check silently false-positive
// if the literal ever failed to parse.
// Non-optional construction via `init(uuid:)` — `init(uuidString:)` returns
// an Optional which would make the equality check silently false-negative
// (zero-IDFA passes through unfiltered) if the literal ever failed to parse.
Prompt To Fix With AI
This is a comment left during a code review.
Path: Sources/SuperwallKit/Analytics/Attribution/AttributionFetcher.swift
Line: 59-61

Comment:
The comment says "silently false-positive" but the failure mode is a false-negative: if `zeroAdvertisingIdentifier` were `nil`, the equality check would return `false`, the `if` block would not fire, and the all-zeros IDFA would pass through unfiltered — the opposite of a false-positive.

```suggestion
  // Non-optional construction via `init(uuid:)` — `init(uuidString:)` returns
  // an Optional which would make the equality check silently false-negative
  // (zero-IDFA passes through unfiltered) if the literal ever failed to parse.
```

How can I resolve this? If you propose a fix, please make it concise.

@yusuftor
Copy link
Copy Markdown
Collaborator Author

Pushed directly to develop instead — see commit 1c81ac5.

@yusuftor yusuftor closed this May 14, 2026
@yusuftor yusuftor deleted the fix-zero-idfa-uuid-comparison branch May 14, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant