Summary
When multiple PC/SC readers are attached and one reader's name is a prefix of another's (e.g. two identical readers appear as ACS ACR1552 1S CL Reader PICC and ACS ACR1552 1S CL Reader PICC 01 on macOS),
passing --reader with the shorter/prefix name silently binds fdsm to the longer-named reader. fdsm prints Using card in <the wrong reader> with no warning.
Environment
- fdsm: current
master (26.01.3-SNAPSHOT); also reproducible on the most recent release JAR
- OS: macOS 15 (Darwin 25.4.0)
- JDK: OpenJDK 21
- Readers: two ACS ACR1552 units attached simultaneously
Reproduction
- Attach two identical USB contactless readers. PC/SC assigns one the bare name (
ACS ACR1552 1S CL Reader PICC) and the second a suffixed name (ACS ACR1552 1S CL Reader PICC 01).
Available readers:
- ACS ACR1552 1S CL Reader SAM
- ACS ACR1552 1S CL Reader SAM 01
- ACS ACR1552 1S CL Reader PICC
- ACS ACR1552 1S CL Reader PICC 01
- Place a card only on the
…PICC 01 reader; leave the …PICC reader empty.
- Run:
java -jar fdsm.jar --reader "ACS ACR1552 1S CL Reader PICC" --offline --card-info
Expected
fdsm binds exactly to the named reader. Since that reader is empty, it fails fast (e.g. SCARD_E_NO_SMARTCARD).
Actual
Using card in ACS ACR1552 1S CL Reader PICC 01
UID: D65B4C15
fdsm silently falls through to the other reader whose name contains the requested string as a substring, and reads its card.
Root cause
tool/src/main/java/com/fidesmo/fdsm/Main.java, lines 262–273. The loop uses contains() on lowercased names (substring match rather than exact) and has no break, so when multiple readers match, the
last enumerated one wins. No card-presence or tiebreaking logic is applied.
Impact
Silent data-corruption path for anyone running fdsm against a station with more than one reader attached. Per the "FDSM for OEMs" docs, "Once a Batch ID is set it cannot be changed" — so a mis-matched
--reader during a --run <batching> operation writes a wrong, permanent Batch ID to the wrong device.
Proposed fix
Change the match to equalsIgnoreCase (still case-insensitive, but exact) and break on first match:
- if (t.getName().toLowerCase().contains(reader.toLowerCase())) {
+ if (t.getName().equalsIgnoreCase(reader)) {
terminal = t;
+ break;
}
Workaround
Pass a --reader value that is not a prefix of any other reader's name (e.g. "…PICC 01" uniquely matches the second reader). There is no clean workaround for the shorter-named reader in a pair like the
above except physically disconnecting the other reader before each call.
Summary
When multiple PC/SC readers are attached and one reader's name is a prefix of another's (e.g. two identical readers appear as
ACS ACR1552 1S CL Reader PICCandACS ACR1552 1S CL Reader PICC 01on macOS),passing
--readerwith the shorter/prefix name silently binds fdsm to the longer-named reader. fdsm printsUsing card in <the wrong reader>with no warning.Environment
master(26.01.3-SNAPSHOT); also reproducible on the most recent release JARReproduction
ACS ACR1552 1S CL Reader PICC) and the second a suffixed name (ACS ACR1552 1S CL Reader PICC 01).…PICC 01reader; leave the…PICCreader empty.Expected
fdsm binds exactly to the named reader. Since that reader is empty, it fails fast (e.g.
SCARD_E_NO_SMARTCARD).Actual
fdsm silently falls through to the other reader whose name contains the requested string as a substring, and reads its card.
Root cause
tool/src/main/java/com/fidesmo/fdsm/Main.java, lines 262–273. The loop usescontains()on lowercased names (substring match rather than exact) and has nobreak, so when multiple readers match, thelast enumerated one wins. No card-presence or tiebreaking logic is applied.
Impact
Silent data-corruption path for anyone running fdsm against a station with more than one reader attached. Per the "FDSM for OEMs" docs, "Once a Batch ID is set it cannot be changed" — so a mis-matched
--readerduring a--run <batching>operation writes a wrong, permanent Batch ID to the wrong device.Proposed fix
Change the match to
equalsIgnoreCase(still case-insensitive, but exact) andbreakon first match:Workaround
Pass a
--readervalue that is not a prefix of any other reader's name (e.g."…PICC 01"uniquely matches the second reader). There is no clean workaround for the shorter-named reader in a pair like theabove except physically disconnecting the other reader before each call.