diff --git a/rustsystem-core/src/lib.rs b/rustsystem-core/src/lib.rs index 9ee0b86..463f569 100644 --- a/rustsystem-core/src/lib.rs +++ b/rustsystem-core/src/lib.rs @@ -44,6 +44,7 @@ pub enum APIErrorCode { InvalidMetaData, InvalidVoteMethod, InvalidVoteLength, + InvalidCandidateId, VotingInactive, SignatureInvalid, @@ -105,6 +106,7 @@ impl APIErrorCode { 409, ), Self::InvalidVoteLength => ("Too many candidates were provided.", 409), + Self::InvalidCandidateId => ("Vote contains an out-of-bounds candidate index.", 422), Self::VotingInactive => ("Vote has already been closed, or it was never opened.", 410), Self::SignatureInvalid => ( diff --git a/rustsystem-server/src/api/voter/vote.rs b/rustsystem-server/src/api/voter/vote.rs index a02ab3e..d79b820 100644 --- a/rustsystem-server/src/api/voter/vote.rs +++ b/rustsystem-server/src/api/voter/vote.rs @@ -42,6 +42,7 @@ impl APIHandler for Submit { validate_metadata(metadata.clone(), round)?; validate_num_choices(choice.clone(), round)?; + validate_candidate_indices(choice.clone(), round)?; validate_signature(validation, round)?; let is_blank = choice.is_none(); @@ -82,6 +83,16 @@ fn validate_num_choices(choice: Option, round: &VoteRound) -> Result<(), Ok(()) } +fn validate_candidate_indices(choice: Option, round: &VoteRound) -> Result<(), APIError> { + if let Some(choices) = choice { + let num_candidates = round.metadata().get_candidates().len(); + if choices.iter().any(|&id| id >= num_candidates) { + return Err(APIError::from_error_code(APIErrorCode::InvalidCandidateId)); + } + } + Ok(()) +} + fn validate_signature( validation: &BallotValidation, round: &mut VoteRound,