Skip to content

Commit be567ce

Browse files
authored
Fix card substring (#341)
## 🎟️ Tracking <!-- Paste the link to the Jira or GitHub issue or otherwise describe / point to where this change is coming from. --> ## 📔 Objective The string subslicing would panic when the subslice would split a multibyte unicode char in two. Using the .chars() API respects the unicode character boundaries. Also enabled a lint to warn against string slicing in the future. ## ⏰ Reminders before review - Contributor guidelines followed - All formatters and local linters executed and passed - Written new unit and / or integration tests where applicable - Protected functional changes with optionality (feature flags) - Used internationalization (i18n) for all UI strings - CI builds passed - Communicated to DevOps any deployment requirements - Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team ## 🦮 Reviewer guidelines <!-- Suggested interactions but feel free to use (or not) as you desire! --> - 👍 (`:+1:`) or similar for great changes - 📝 (`:memo:`) or ℹ️ (`:information_source:`) for notes or general info - ❓ (`:question:`) for questions - 🤔 (`:thinking:`) or 💭 (`:thought_balloon:`) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion - 🎨 (`:art:`) for suggestions / improvements - ❌ (`:x:`) or ⚠️ (`:warning:`) for more significant problems or concerns needing attention - 🌱 (`:seedling:`) or ♻️ (`:recycle:`) for future improvements or indications of technical debt - ⛏ (`:pick:`) for minor or nitpick changes
1 parent f43bbc6 commit be567ce

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ pkcs5 = { git = "https://github.com/bitwarden/rustcrypto-formats.git", rev = "2b
8383
[workspace.lints.clippy]
8484
unused_async = "deny"
8585
unwrap_used = "deny"
86+
string_slice = "warn"
8687

8788
[workspace.lints.rust]
8889
missing_docs = "warn"

crates/bitwarden-vault/src/cipher/card.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,20 +173,21 @@ fn build_subtitle_card(brand: Option<String>, number: Option<String>) -> String
173173
}
174174

175175
if let Some(number) = number {
176-
let number_len = number.len();
176+
let number_chars: Vec<_> = number.chars().collect();
177+
let number_len = number_chars.len();
177178
if number_len > 4 {
178179
if !subtitle.is_empty() {
179180
subtitle.push_str(", ");
180181
}
181182

182183
// On AMEX cards we show 5 digits instead of 4
183-
let digit_count = match &number[0..2] {
184-
"34" | "37" => 5,
184+
let digit_count = match number_chars[0..2] {
185+
['3', '4'] | ['3', '7'] => 5,
185186
_ => 4,
186187
};
187188

188189
subtitle.push('*');
189-
subtitle.push_str(&number[(number_len - digit_count)..]);
190+
subtitle.extend(number_chars.iter().skip(number_len - digit_count));
190191
}
191192
}
192193

@@ -269,6 +270,15 @@ mod tests {
269270
);
270271
}
271272

273+
#[test]
274+
fn test_build_subtitle_card_unicode() {
275+
let brand = Some("Visa".to_owned());
276+
let number = Some("•••• 3278".to_owned());
277+
278+
let subtitle = build_subtitle_card(brand, number);
279+
assert_eq!(subtitle, "Visa, *3278");
280+
}
281+
272282
#[test]
273283
fn test_get_copyable_fields_number() {
274284
let card = Card {

0 commit comments

Comments
 (0)