Duplicate :
|
FULL PRODUCT VERSION : java version "1.7.0_06-ea" Java(TM) SE Runtime Environment (build 1.7.0_06-ea-b08) Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode) ADDITIONAL OS VERSION INFORMATION : Mac OS X only EXTRA RELEVANT SYSTEM CONFIGURATION : Smart Card reader attached to an OS X system along with a smart card. A DESCRIPTION OF THE PROBLEM : 7195480, but I can't find a way to add more details. CardTerminal.isCardPresent() always returns false. REGRESSION. Last worked in version 6u31 STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Run this code on OS X with Oracle Java 7 TerminalFactory factory = TerminalFactory.getDefault(); List<CardTerminal> terminals = factory.terminals().list(); System.out.println("Terminals: " + terminals); CardTerminal terminal = terminals.get(0); System.out.println(terminal.isCardPresent()); // Always false EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - Returns true when a card is present, false otherwise ACTUAL - CardTerminal.isCardPresent() always returns false. The main issue here is the native layer in Java is reading the wrong part of the struct SCARD_READERSTATE after calling SCardGetStatusChange. From Java_sun_security_smartcardio_PCSC_SCardGetStatusChange after the malloc call: (gdb) c Continuing. Breakpoint 3, 0x000000010aa225b2 in Java_sun_security_smartcardio_PCSC_SCardGetStatusChange () 3: x/8xw 4300546608 0x100552230: 0x00554aa0 0x00000001 0x00000000 0x00000000 0x100552240: 0x00000000 0x00000022 0x00000013 0x0096db3b ^^^^^^^^ ^^^^^^^^ | +--- Number of bytes in ATR +--- Event State 2: /x $rax = 0x0 1: x/i $rip 0x10aa225b2 <Java_sun_security_smartcardio_PCSC_SCardGetStatusChange+265>: mov %rax,-0x50(%rbp) (gdb) set {int}0x100552248 = 0xdeadbeef (gdb) display 3: x/8xw 4300546608 0x100552230: 0x00554aa0 0x00000001 0x00000000 0x00000000 0x100552240: 0x00000000 0x00000022 0xdeadbeef 0x0096db3b ^^^^^^^^ ^^^^^^^^ | +--- Number of bytes in ATR +--- Event State 2: /x $rax = 0x0 1: x/i $rip 0x10aa225b2 <Java_sun_security_smartcardio_PCSC_SCardGetStatusChange+265>: mov %rax,-0x50(%rbp) (gdb) c Continuing. deadbeef <-- Printed from the JVM, the result of directly calling SCardGetStatusChange via reflection ^^^^^^^^ | +---- Now in the JVM from a direct reflection call to SCardGetStatusChange Program exited normally. (gdb) REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- TerminalFactory factory = TerminalFactory.getDefault(); List<CardTerminal> terminals = factory.terminals().list(); System.out.println("Terminals: " + terminals); CardTerminal terminal = terminals.get(0); System.out.println(terminal.isCardPresent()); // Always false ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : Since in OS X the method returns the number of bytes in the ATR rather than the event state, the main workaround is to test if the number of ATR bytes is non-zero. To do so, code must be written that restricts its execution to Java versions after 1.7 and OS X only. The code must use reflection to directly call SCardGetStatusChange and check the value of the returned ATR size.