Skip to content

Important: integer division loses score precision #20

@0xdevcollins

Description

@0xdevcollins

Severity: Important (fairness)

let avg = if sub.score_count > 0 {
    sub.total_score / sub.score_count
} else { 0 };

Submissions with averages 89.6 and 89.4 both round to 89 and tie. Real ranking lost.

Fix

Sort by ratio without division. Compare (a.total_score * b.score_count) vs (b.total_score * a.score_count):

fn cmp_avg(a_sum: u32, a_cnt: u32, b_sum: u32, b_cnt: u32) -> core::cmp::Ordering {
    // a/a_cnt vs b/b_cnt  ->  a*b_cnt vs b*a_cnt  (no precision loss)
    let lhs = (a_sum as u64) * (b_cnt as u64);
    let rhs = (b_sum as u64) * (a_cnt as u64);
    lhs.cmp(&rhs)
}

Tests

  • 89.6 ranks above 89.4
  • (95, 2 judges) ranks correctly vs (286, 3 judges)
  • Overflow: max scores * max counts fits in u64

Metadata

Metadata

Assignees

No one assigned

    Labels

    audit-findingSurfaced during internal audit / reviewenhancementNew feature or request

    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