Skip to content

Commit 7e305ad

Browse files
committed
8255405: sun/net/ftp/imp/FtpClient uses SimpleDateFormat in not thread-safe manner
Reviewed-by: chegar, ryadav, dfuchs
1 parent d82a6dc commit 7e305ad

File tree

2 files changed

+21
-33
lines changed

2 files changed

+21
-33
lines changed

src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java

+14-28
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,16 @@
2929
import java.security.AccessController;
3030
import java.security.PrivilegedAction;
3131
import java.text.DateFormat;
32-
import java.text.ParseException;
33-
import java.text.SimpleDateFormat;
32+
import java.time.ZoneOffset;
33+
import java.time.ZonedDateTime;
34+
import java.time.format.DateTimeFormatter;
35+
import java.time.format.DateTimeParseException;
3436
import java.util.ArrayList;
3537
import java.util.Base64;
3638
import java.util.Calendar;
3739
import java.util.Date;
3840
import java.util.Iterator;
3941
import java.util.List;
40-
import java.util.TimeZone;
4142
import java.util.Vector;
4243
import java.util.regex.Matcher;
4344
import java.util.regex.Pattern;
@@ -1739,19 +1740,8 @@ public long getSize(String path) throws sun.net.ftp.FtpProtocolException, IOExce
17391740
return -1;
17401741
}
17411742

1742-
private static final SimpleDateFormat[] dateFormats;
1743-
1744-
static {
1745-
String[] formats = {
1746-
"yyyyMMddHHmmss.SSS",
1747-
"yyyyMMddHHmmss"
1748-
};
1749-
dateFormats = new SimpleDateFormat[formats.length];
1750-
for (int i = 0; i < formats.length; ++i) {
1751-
dateFormats[i] = new SimpleDateFormat(formats[i]);
1752-
dateFormats[i].setTimeZone(TimeZone.getTimeZone("GMT"));
1753-
}
1754-
}
1743+
private static final DateTimeFormatter RFC3659_DATETIME_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss[.SSS]")
1744+
.withZone(ZoneOffset.UTC);
17551745

17561746
/**
17571747
* Issues the MDTM [path] command to the server to get the modification
@@ -1768,24 +1758,20 @@ public long getSize(String path) throws sun.net.ftp.FtpProtocolException, IOExce
17681758
public Date getLastModified(String path) throws sun.net.ftp.FtpProtocolException, IOException {
17691759
issueCommandCheck("MDTM " + path);
17701760
if (lastReplyCode == FtpReplyCode.FILE_STATUS) {
1771-
String s = getResponseString().substring(4);
1772-
return parseRfc3659TimeValue(s);
1761+
String s = getResponseString();
1762+
return parseRfc3659TimeValue(s.substring(4, s.length() - 1));
17731763
}
17741764
return null;
17751765
}
17761766

17771767
private static Date parseRfc3659TimeValue(String s) {
1778-
Date d = null;
1779-
for (SimpleDateFormat dateFormat : dateFormats) {
1780-
try {
1781-
d = dateFormat.parse(s);
1782-
} catch (ParseException ex) {
1783-
}
1784-
if (d != null) {
1785-
return d;
1786-
}
1768+
Date result = null;
1769+
try {
1770+
var d = ZonedDateTime.parse(s, RFC3659_DATETIME_FORMAT);
1771+
result = Date.from(d.toInstant());
1772+
} catch (DateTimeParseException ex) {
17871773
}
1788-
return d;
1774+
return result;
17891775
}
17901776

17911777
/**

test/jdk/sun/net/ftp/TestFtpTimeValue.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
* @library /test/lib
2929
* @modules java.base/sun.net.ftp
3030
* @build jdk.test.lib.Asserts
31-
* @run main TestFtpTimeValue
31+
* @run main/othervm -Duser.timezone=UTC TestFtpTimeValue
32+
* @run main/othervm -Duser.timezone=America/Los_Angeles TestFtpTimeValue
3233
*/
3334

3435
import jdk.test.lib.Asserts;
@@ -61,23 +62,24 @@ private enum TestCase {
6162
calendar.set(year, month - 1, day, hrs, min, sec);
6263
calendar.set(Calendar.MILLISECOND, milliseconds);
6364
expectedCreated = calendar.getTime();
64-
var s = String.format("%4d%2d%2d%2d%2d%2d", year, month, day, hrs, min, sec);
65+
var s = String.format("%4d%02d%02d%02d%02d%02d", year, month, day, hrs, min, sec);
6566
if (milliseconds != 0) {
66-
s += "." + String.format("%3d", milliseconds);
67+
s += "." + String.format("%03d", milliseconds);
6768
}
6869
create = s;
6970

7071
calendar.add(GregorianCalendar.SECOND, 1);
7172
expectedModified = calendar.getTime();
72-
s = String.format("%4d%2d%2d%2d%2d%2d", year, month, day, hrs, min, sec + 1);
73+
s = String.format("%4d%02d%02d%02d%02d%02d", year, month, day, hrs, min, sec + 1);
7374
if (milliseconds != 0) {
74-
s += "." + String.format("%3d", milliseconds);
75+
s += "." + String.format("%03d", milliseconds);
7576
}
7677
modify = s;
7778
}
7879
}
7980

8081
public static void main(String[] args) throws Exception {
82+
System.out.println("user.timezone: " + System.getProperty("user.timezone"));
8183
try (FtpServer server = new FtpServer();
8284
FtpClient client = FtpClient.create()) {
8385
(new Thread(server)).start();

0 commit comments

Comments
 (0)