From a4feeb01945e039b39a246f96a1a91b0e4836f01 Mon Sep 17 00:00:00 2001 From: Matthias Sohn Date: Sat, 28 Jan 2017 15:06:15 +0100 Subject: [PATCH] Don't rely on default locale when using toUpperCase() and toLowerCase() Otherwise these methods may produce unexpected results if used for strings that are intended to be interpreted locale independently. Examples are programming language identifiers, protocol keys, and HTML tags. For instance, "TITLE".toLowerCase() in a Turkish locale returns "t\u0131tle", where '\u0131' is the LATIN SMALL LETTER DOTLESS I character. See https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#toLowerCase-- http://blog.thetaphi.de/2012/07/default-locales-default-charsets-and.html Bug: 511238 Change-Id: Id8d8f37d84d62239c918b81f8d883ed798d87656 Signed-off-by: Matthias Sohn --- .../src/org/eclipse/jgit/lfs/server/s3/SignerV4.java | 6 ++++-- .../tst/org/eclipse/jgit/lfs/lib/LongObjectIdTest.java | 3 ++- .../src/org/eclipse/jgit/lfs/LfsPointer.java | 3 ++- org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java | 5 +++-- org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java | 4 +++- .../tst/org/eclipse/jgit/lib/ObjectIdTest.java | 4 +++- .../tst/org/eclipse/jgit/transport/WalkEncryptionTest.java | 5 +++-- .../src/org/eclipse/jgit/api/MergeCommand.java | 3 ++- .../eclipse/jgit/internal/storage/file/FileRepository.java | 3 ++- org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java | 3 ++- .../src/org/eclipse/jgit/patch/FormatError.java | 4 +++- .../src/org/eclipse/jgit/revwalk/FooterKey.java | 4 +++- .../src/org/eclipse/jgit/submodule/SubmoduleWalk.java | 4 +++- .../src/org/eclipse/jgit/transport/HttpAuthMethod.java | 6 ++++-- org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRC.java | 3 ++- .../src/org/eclipse/jgit/transport/TransportGitSsh.java | 6 ++++-- .../src/org/eclipse/jgit/transport/WalkEncryption.java | 7 ++++--- org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java | 4 +++- 18 files changed, 52 insertions(+), 25 deletions(-) diff --git a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/s3/SignerV4.java b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/s3/SignerV4.java index f95b605c8..4149484c8 100644 --- a/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/s3/SignerV4.java +++ b/org.eclipse.jgit.lfs.server/src/org/eclipse/jgit/lfs/server/s3/SignerV4.java @@ -57,6 +57,7 @@ import java.util.Date; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.SimpleTimeZone; import java.util.SortedMap; @@ -247,7 +248,7 @@ private static String canonicalizeHeaderNames( for (String header : sortedHeaders) { if (buffer.length() > 0) buffer.append(";"); //$NON-NLS-1$ - buffer.append(header.toLowerCase()); + buffer.append(header.toLowerCase(Locale.ROOT)); } return buffer.toString(); @@ -265,7 +266,8 @@ private static String canonicalizeHeaderString( StringBuilder buffer = new StringBuilder(); for (String key : sortedHeaders) { - buffer.append(key.toLowerCase().replaceAll("\\s+", " ") + ":" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + buffer.append( + key.toLowerCase(Locale.ROOT).replaceAll("\\s+", " ") + ":" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + headers.get(key).replaceAll("\\s+", " ")); //$NON-NLS-1$//$NON-NLS-2$ buffer.append("\n"); //$NON-NLS-1$ } diff --git a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LongObjectIdTest.java b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LongObjectIdTest.java index 435a2a3c3..68dcf806b 100644 --- a/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LongObjectIdTest.java +++ b/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/lib/LongObjectIdTest.java @@ -57,6 +57,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Locale; import org.eclipse.jgit.junit.JGitTestUtil; import org.eclipse.jgit.lfs.errors.InvalidLongObjectIdException; @@ -152,7 +153,7 @@ public void test010_toString() { public void test011_toString() { final String x = "0123456789ABCDEFabcdef01234567890123456789ABCDEFabcdef0123456789"; final LongObjectId oid = LongObjectId.fromString(x); - assertEquals(x.toLowerCase(), oid.name()); + assertEquals(x.toLowerCase(Locale.ROOT), oid.name()); } @Test diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/LfsPointer.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/LfsPointer.java index 0aee1aadd..0f62025be 100644 --- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/LfsPointer.java +++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/LfsPointer.java @@ -51,6 +51,7 @@ import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; +import java.util.Locale; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.lfs.lib.AnyLongObjectId; @@ -79,7 +80,7 @@ public class LfsPointer { * evaluate to "sha256" */ public static final String HASH_FUNCTION_NAME = Constants.LONG_HASH_FUNCTION - .toLowerCase().replace("-", ""); //$NON-NLS-1$ //$NON-NLS-2$ + .toLowerCase(Locale.ROOT).replace("-", ""); //$NON-NLS-1$ //$NON-NLS-2$ private AnyLongObjectId oid; diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java index 62e77285b..82c401ff8 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java @@ -53,6 +53,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -102,8 +103,8 @@ void addAdditionalNoteRef(String notesRef) { @Option(name = "--date", usage = "usage_date") void dateFormat(String date) { - if (date.toLowerCase().equals(date)) - date = date.toUpperCase(); + if (date.toLowerCase(Locale.ROOT).equals(date)) + date = date.toUpperCase(Locale.ROOT); dateFormatter = new GitDateFormatter(Format.valueOf(date)); } diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java index a0f4d06d4..7d111ffcc 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java @@ -53,6 +53,7 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import org.eclipse.jgit.awtui.AwtAuthenticator; import org.eclipse.jgit.awtui.AwtCredentialsProvider; @@ -240,7 +241,8 @@ private void execute(final String[] argv) throws Exception { } if (version) { - String cmdId = Version.class.getSimpleName().toLowerCase(); + String cmdId = Version.class.getSimpleName() + .toLowerCase(Locale.ROOT); subcommand = CommandCatalog.get(cmdId).create(); } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java index 80ece1c26..0adea0baa 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectIdTest.java @@ -49,6 +49,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.util.Locale; + import org.eclipse.jgit.errors.InvalidObjectIdException; import org.junit.Test; @@ -122,7 +124,7 @@ public void test010_toString() { public void test011_toString() { final String x = "0123456789ABCDEFabcdef1234567890abcdefAB"; final ObjectId oid = ObjectId.fromString(x); - assertEquals(x.toLowerCase(), oid.name()); + assertEquals(x.toLowerCase(Locale.ROOT), oid.name()); } @Test(expected = InvalidObjectIdException.class) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/WalkEncryptionTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/WalkEncryptionTest.java index cc5870ebf..a60bb39ce 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/WalkEncryptionTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/WalkEncryptionTest.java @@ -85,6 +85,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Locale; import java.util.Properties; import java.util.Set; import java.util.TreeSet; @@ -461,7 +462,7 @@ static List cryptoCipherList(String regex) { Set source = Security.getAlgorithms("Cipher"); Set target = new TreeSet(); for (String algo : source) { - algo = algo.toUpperCase(); + algo = algo.toUpperCase(Locale.ROOT); if (algo.matches(regex)) { target.add(algo); } @@ -759,7 +760,7 @@ static boolean isAlgorithmPresent(String algorithm) { for (String source : cipherSet) { // Standard names are not case-sensitive. // http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html - String target = algorithm.toUpperCase(); + String target = algorithm.toUpperCase(Locale.ROOT); if (source.equalsIgnoreCase(target)) { return true; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java index ced186371..2daa0d1a3 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java @@ -50,6 +50,7 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Map; import org.eclipse.jgit.api.MergeResult.MergeStatus; @@ -134,7 +135,7 @@ public enum FastForwardMode implements ConfigEnum { FF_ONLY; public String toConfigValue() { - return "--" + name().toLowerCase().replace('_', '-'); //$NON-NLS-1$ + return "--" + name().toLowerCase(Locale.ROOT).replace('_', '-'); //$NON-NLS-1$ } public boolean matchConfigValue(String in) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java index 0388acbba..16315a5b5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileRepository.java @@ -55,6 +55,7 @@ import java.text.MessageFormat; import java.text.ParseException; import java.util.HashSet; +import java.util.Locale; import java.util.Objects; import java.util.Set; @@ -342,7 +343,7 @@ && getDirectory().getName().startsWith(".")) //$NON-NLS-1$ if (symLinks != null) cfg.setString(ConfigConstants.CONFIG_CORE_SECTION, null, ConfigConstants.CONFIG_KEY_SYMLINKS, symLinks.name() - .toLowerCase()); + .toLowerCase(Locale.ROOT)); cfg.setInt(ConfigConstants.CONFIG_CORE_SECTION, null, ConfigConstants.CONFIG_KEY_REPO_FORMAT_VERSION, 0); cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null, diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java index 8fe8a96e9..ec771a24f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java @@ -58,6 +58,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -895,7 +896,7 @@ public > void setEnum(final String section, if (value instanceof ConfigEnum) n = ((ConfigEnum) value).toConfigValue(); else - n = value.name().toLowerCase().replace('_', ' '); + n = value.name().toLowerCase(Locale.ROOT).replace('_', ' '); setString(section, subsection, name, n); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/FormatError.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/FormatError.java index 245b3ee59..767cb2430 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/FormatError.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/FormatError.java @@ -43,6 +43,8 @@ package org.eclipse.jgit.patch; +import java.util.Locale; + import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.util.RawParseUtils; @@ -102,7 +104,7 @@ public String getLineText() { @Override public String toString() { final StringBuilder r = new StringBuilder(); - r.append(getSeverity().name().toLowerCase()); + r.append(getSeverity().name().toLowerCase(Locale.ROOT)); r.append(": at offset "); //$NON-NLS-1$ r.append(getOffset()); r.append(": "); //$NON-NLS-1$ diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterKey.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterKey.java index 319b819a7..36965f499 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterKey.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/FooterKey.java @@ -43,6 +43,8 @@ package org.eclipse.jgit.revwalk; +import java.util.Locale; + import org.eclipse.jgit.lib.Constants; /** Case insensitive key for a {@link FooterLine}. */ @@ -68,7 +70,7 @@ public final class FooterKey { */ public FooterKey(final String keyName) { name = keyName; - raw = Constants.encode(keyName.toLowerCase()); + raw = Constants.encode(keyName.toLowerCase(Locale.ROOT)); } /** @return name of this footer line. */ diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java index 5b9e8d902..a10f3d711 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java @@ -45,6 +45,7 @@ import java.io.File; import java.io.IOException; import java.text.MessageFormat; +import java.util.Locale; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheIterator; @@ -663,7 +664,8 @@ public IgnoreSubmoduleMode getModulesIgnore() throws IOException, ConfigConstants.CONFIG_KEY_IGNORE); if (name == null) return null; - return IgnoreSubmoduleMode.valueOf(name.trim().toUpperCase()); + return IgnoreSubmoduleMode + .valueOf(name.trim().toUpperCase(Locale.ROOT)); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java index 81e6904bf..4256fe47d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java @@ -56,6 +56,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Random; @@ -168,7 +169,8 @@ static HttpAuthMethod scanResponse(final HttpConnection conn, SCHEMA_NAME_SEPARATOR, 2); try { - Type methodType = Type.valueOf(valuePart[0].toUpperCase()); + Type methodType = Type.valueOf( + valuePart[0].toUpperCase(Locale.ROOT)); if ((ignoreTypes != null) && (ignoreTypes.contains(methodType))) { @@ -540,7 +542,7 @@ void configureRequest(HttpConnection conn) throws IOException { GSSManager gssManager = GSS_MANAGER_FACTORY.newInstance(conn .getURL()); String host = conn.getURL().getHost(); - String peerName = "HTTP@" + host.toLowerCase(); //$NON-NLS-1$ + String peerName = "HTTP@" + host.toLowerCase(Locale.ROOT); //$NON-NLS-1$ try { GSSName gssName = gssManager.createName(peerName, GSSName.NT_HOSTBASED_SERVICE); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRC.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRC.java index bacab7e21..8855f9656 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRC.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRC.java @@ -48,6 +48,7 @@ import java.io.IOException; import java.util.Collection; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import java.util.TreeMap; import java.util.regex.Matcher; @@ -230,7 +231,7 @@ private void parse() { matcher.reset(line); while (matcher.find()) { - String command = matcher.group().toLowerCase(); + String command = matcher.group().toLowerCase(Locale.ROOT); if (command.startsWith("#")) { //$NON-NLS-1$ matcher.reset(""); //$NON-NLS-1$ continue; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java index da98e8c9e..6bdf905e4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java @@ -56,6 +56,7 @@ import java.util.EnumSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Locale; import java.util.Set; import org.eclipse.jgit.errors.NoRemoteRepositoryException; @@ -217,11 +218,12 @@ private class ExtSession implements RemoteSession { public Process exec(String command, int timeout) throws TransportException { String ssh = SystemReader.getInstance().getenv("GIT_SSH"); //$NON-NLS-1$ - boolean putty = ssh.toLowerCase().contains("plink"); //$NON-NLS-1$ + boolean putty = ssh.toLowerCase(Locale.ROOT).contains("plink"); //$NON-NLS-1$ List args = new ArrayList(); args.add(ssh); - if (putty && !ssh.toLowerCase().contains("tortoiseplink")) //$NON-NLS-1$ + if (putty + && !ssh.toLowerCase(Locale.ROOT).contains("tortoiseplink")) //$NON-NLS-1$ args.add("-batch"); //$NON-NLS-1$ if (0 < getURI().getPort()) { args.add(putty ? "-P" : "-p"); //$NON-NLS-1$ //$NON-NLS-2$ diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkEncryption.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkEncryption.java index 4c3fdd84f..333e09d46 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkEncryption.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkEncryption.java @@ -52,6 +52,7 @@ import java.security.spec.AlgorithmParameterSpec; import java.security.spec.KeySpec; import java.text.MessageFormat; +import java.util.Locale; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -192,7 +193,7 @@ static class JetS3tV2 extends WalkEncryption { // Standard names are not case-sensitive. // http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html - String cryptoName = cryptoAlg.toUpperCase(); + String cryptoName = cryptoAlg.toUpperCase(Locale.ROOT); if (!cryptoName.startsWith("PBE")) //$NON-NLS-1$ throw new GeneralSecurityException(JGitText.get().encryptionOnlyPBE); @@ -373,7 +374,7 @@ static abstract class SymmetricEncryption extends WalkEncryption SecretKey keyBase = factory.generateSecret(keySpec); - String name = cipherAlgo.toUpperCase(); + String name = cipherAlgo.toUpperCase(Locale.ROOT); Matcher matcherPBE = Pattern.compile(REGEX_PBE).matcher(name); Matcher matcherTrans = Pattern.compile(REGEX_TRANS).matcher(name); if (matcherPBE.matches()) { @@ -506,7 +507,7 @@ static Properties wrap(String algo, String pass) { JGitV1(String algo, String pass) throws GeneralSecurityException { super(wrap(algo, pass)); - String name = cipherAlgo.toUpperCase(); + String name = cipherAlgo.toUpperCase(Locale.ROOT); Matcher matcherPBE = Pattern.compile(REGEX_PBE).matcher(name); if (!matcherPBE.matches()) throw new GeneralSecurityException( diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java index aa101f73f..c04dfa961 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java @@ -65,6 +65,7 @@ import java.text.Normalizer.Form; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.regex.Pattern; import org.eclipse.jgit.internal.JGitText; @@ -542,7 +543,8 @@ else if (!ignoreCase public static boolean isStaleFileHandle(IOException ioe) { String msg = ioe.getMessage(); return msg != null - && msg.toLowerCase().matches("stale .*file .*handle"); //$NON-NLS-1$ + && msg.toLowerCase(Locale.ROOT) + .matches("stale .*file .*handle"); //$NON-NLS-1$ } /**