SubmittedCWE-193 — Off-by-One Error
GeneratePinCode off-by-one loop condition returns short PIN ~16% of the time, causing intermittent pairing failure
View Upstream Issuegitcode.com/openharmony/distributedhardware_device_manager/issues/2440CWE:CWE-193 — Off-by-One Error
Repository:distributedhardware_device_manager
Date:2026-05-19
Affected Version:5.0+
Component:dm_random
Reporter:Toan
Affected Files
utils/src/dm_random.cppSummary
GeneratePinCode(pinLength) in utils/src/dm_random.cpp:101 returns pinLength - 1 characters approximately 1/pinLength of the time (~16% for 6-digit PINs). This causes device pairing to fail intermittently with no clear error.
Vulnerable Code
// utils/src/dm_random.cpp:101
// left_digit_count = pinLength - 1
while (pinCode.length() < left_digit_count) { // '<' allows exact-length exit
When std::to_string(gen()) appends a sum that brings the total to exactly pinLength - 1, the loop exits one iteration early. substr(0, pinLength) on a shorter string silently returns fewer characters.
Example (pinLength=6)
Initial: GenRandInt(1,9) = "3" → length 1
Iter 1: gen() = "7254" → length 5
Check: 5 < 5? FALSE → exit ← too early
Result: substr(0, 6) on 5-char string → "37254" ← 5 chars, not 6
Downstream validation rejects this: "37254".length() < DM_MIN_PINCODE_SIZE (6) → pairing fails.
Trigger Conditions
GeneratePinCodeis called withpinLength(typically 6)- Random generation produces a sum that brings
pinCode.length()to exactlyleft_digit_count(pinLength - 1) - Loop condition
pinCode.length() < left_digit_countevaluates false, exits early substr(0, pinLength)on the shorter string returns a PIN with fewer characters- Downstream check rejects the short PIN → device pairing fails
Impact
- Intermittent pairing failure: ~16% of 6-digit PIN generations produce a short PIN, causing device pairing to fail
- No clear error: The short PIN is silently generated; the failure manifests downstream, making diagnosis difficult
- Affected callers:
ExportAuthInfoand any code path callingGeneratePinCode
Suggested Fix
- while (pinCode.length() < left_digit_count) {
+ while (pinCode.length() <= left_digit_count) {
substr(0, pinLength) already bounds the result, so overshooting is harmless. The <= condition ensures the loop always runs enough iterations.