Avatar color hash has drifted between PHP (crc32) and JS (custom hash) — same user shows different colors #31

Open
opened 2026-08-31 21:29:41 -04:00 by jared · 0 comments
Owner

Severity: High (cosmetic but definite bug)

views/TicketView.php's PHP renderComment() computes avatar color via crc32($displayName) % 4. The JS in assets/js/ticket.js (avatarColorClass(), ~lines 188-194) claims in a comment to "mirror the PHP crc32 % 4 logic" but actually implements a different rolling hash ((hash<<5)-hash+charCode, classic String.hashCode()-style, not CRC-32).

Impact: For the same displayName, the two algorithms generally disagree on % 4, so the same user's avatar color can visibly flip between a server-rendered comment (initial page load) and a client-rendered one (new comment / reply / "Load more" pagination) on the same page.

Fix: Implement a real CRC-32 in JS (or a shared simple hash used by both sides) so the two stay in sync — this is exactly the kind of manually-synced cross-language logic that's easy to silently drift, and it already has.

**Severity:** High (cosmetic but definite bug) `views/TicketView.php`'s PHP `renderComment()` computes avatar color via `crc32($displayName) % 4`. The JS in `assets/js/ticket.js` (`avatarColorClass()`, ~lines 188-194) claims in a comment to "mirror the PHP crc32 % 4 logic" but actually implements a different rolling hash (`(hash<<5)-hash+charCode`, classic `String.hashCode()`-style, not CRC-32). **Impact:** For the same `displayName`, the two algorithms generally disagree on `% 4`, so the same user's avatar color can visibly flip between a server-rendered comment (initial page load) and a client-rendered one (new comment / reply / "Load more" pagination) on the same page. **Fix:** Implement a real CRC-32 in JS (or a shared simple hash used by both sides) so the two stay in sync — this is exactly the kind of manually-synced cross-language logic that's easy to silently drift, and it already has.
jared added the priority/highux labels 2026-09-08 10:15:43 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/tinker_tickets#31