Skip to content

Commit faf5c3d

Browse files
committed
Polish toLower/UpperCase Usage
Apply the common security hardening technique of specifying Locale when calling toUpperCase and toLowerCase Closes gh-964
1 parent 5cfae77 commit faf5c3d

File tree

8 files changed

+41
-16
lines changed

8 files changed

+41
-16
lines changed

Diff for: core/src/main/java/org/springframework/ldap/core/LdapRdnComponent.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.io.Serializable;
2020
import java.net.URI;
2121
import java.net.URISyntaxException;
22+
import java.util.Locale;
2223

2324
import org.slf4j.Logger;
2425
import org.slf4j.LoggerFactory;
@@ -75,10 +76,10 @@ public LdapRdnComponent(String key, String value, boolean decodeValue) {
7576

7677
String caseFold = System.getProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY);
7778
if (!StringUtils.hasText(caseFold) || caseFold.equals(DistinguishedName.KEY_CASE_FOLD_LOWER)) {
78-
this.key = key.toLowerCase();
79+
this.key = key.toLowerCase(Locale.ROOT);
7980
}
8081
else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_UPPER)) {
81-
this.key = key.toUpperCase();
82+
this.key = key.toUpperCase(Locale.ROOT);
8283
}
8384
else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_NONE)) {
8485
this.key = key;
@@ -88,7 +89,7 @@ else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_NONE)) {
8889
+ "; expected \"" + DistinguishedName.KEY_CASE_FOLD_LOWER + "\", \""
8990
+ DistinguishedName.KEY_CASE_FOLD_UPPER + "\", or \"" + DistinguishedName.KEY_CASE_FOLD_NONE
9091
+ "\"");
91-
this.key = key.toLowerCase();
92+
this.key = key.toLowerCase(Locale.ROOT);
9293
}
9394
if (decodeValue) {
9495
this.value = LdapEncoder.nameDecode(value);
@@ -203,7 +204,7 @@ public boolean equals(Object obj) {
203204
*/
204205
@Override
205206
public int hashCode() {
206-
return this.key.toUpperCase().hashCode() ^ this.value.toUpperCase().hashCode();
207+
return this.key.toUpperCase(Locale.ROOT).hashCode() ^ this.value.toUpperCase(Locale.ROOT).hashCode();
207208
}
208209

209210
/*
@@ -228,9 +229,9 @@ public int compareTo(Object obj) {
228229

229230
// It's safe to compare directly against key and value,
230231
// because they are validated not to be null on instance creation.
231-
int keyCompare = this.key.toLowerCase().compareTo(that.key.toLowerCase());
232+
int keyCompare = this.key.toLowerCase(Locale.ROOT).compareTo(that.key.toLowerCase(Locale.ROOT));
232233
if (keyCompare == 0) {
233-
return this.value.toLowerCase().compareTo(that.value.toLowerCase());
234+
return this.value.toLowerCase(Locale.ROOT).compareTo(that.value.toLowerCase(Locale.ROOT));
234235
}
235236
else {
236237
return keyCompare;

Diff for: core/src/main/java/org/springframework/ldap/core/NameAwareAttributes.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.ldap.core;
1818

1919
import java.util.HashMap;
20+
import java.util.Locale;
2021
import java.util.Map;
2122

2223
import javax.naming.NamingEnumeration;
@@ -67,7 +68,7 @@ public int size() {
6768
@Override
6869
public NameAwareAttribute get(String attrID) {
6970
Assert.hasLength(attrID, "Attribute ID must not be empty");
70-
return this.attributes.get(attrID.toLowerCase());
71+
return this.attributes.get(attrID.toLowerCase(Locale.ROOT));
7172
}
7273

7374
@Override
@@ -84,7 +85,7 @@ public NamingEnumeration<String> getIDs() {
8485
public Attribute put(String attrID, Object val) {
8586
Assert.hasLength(attrID, "Attribute ID must not be empty");
8687
NameAwareAttribute newAttribute = new NameAwareAttribute(attrID, val);
87-
this.attributes.put(attrID.toLowerCase(), newAttribute);
88+
this.attributes.put(attrID.toLowerCase(Locale.ROOT), newAttribute);
8889

8990
return newAttribute;
9091
}
@@ -93,15 +94,15 @@ public Attribute put(String attrID, Object val) {
9394
public Attribute put(Attribute attr) {
9495
Assert.notNull(attr, "Attribute must not be null");
9596
NameAwareAttribute newAttribute = new NameAwareAttribute(attr);
96-
this.attributes.put(attr.getID().toLowerCase(), newAttribute);
97+
this.attributes.put(attr.getID().toLowerCase(Locale.ROOT), newAttribute);
9798

9899
return newAttribute;
99100
}
100101

101102
@Override
102103
public Attribute remove(String attrID) {
103104
Assert.hasLength(attrID, "Attribute ID must not be empty");
104-
return this.attributes.remove(attrID.toLowerCase());
105+
return this.attributes.remove(attrID.toLowerCase(Locale.ROOT));
105106
}
106107

107108
@Override

Diff for: core/src/main/java/org/springframework/ldap/odm/core/impl/CaseIgnoreString.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.ldap.odm.core.impl;
1818

19+
import java.util.Locale;
20+
1921
import org.springframework.util.Assert;
2022

2123
// A case independent String wrapper.
@@ -28,7 +30,7 @@
2830
CaseIgnoreString(String string) {
2931
Assert.notNull(string, "string must not be null");
3032
this.string = string;
31-
this.hashCode = string.toUpperCase().hashCode();
33+
this.hashCode = string.toUpperCase(Locale.ROOT).hashCode();
3234
}
3335

3436
@Override

Diff for: core/src/main/java/org/springframework/ldap/support/LdapEncoder.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.ldap.support;
1818

1919
import java.util.Base64;
20+
import java.util.Locale;
2021

2122
import org.springframework.ldap.BadLdapGrammarException;
2223
import org.springframework.util.Assert;
@@ -81,7 +82,7 @@ private LdapEncoder() {
8182

8283
protected static String toTwoCharHex(char c) {
8384

84-
String raw = Integer.toHexString(c).toUpperCase();
85+
String raw = Integer.toHexString(c).toUpperCase(Locale.ROOT);
8586

8687
if (raw.length() > 1) {
8788
return raw;

Diff for: etc/checkstyle/checkstyle.xml

+16
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,21 @@
2626
<property name="message" value="Please use assertThatExceptionOfType." />
2727
<property name="ignoreComments" value="true" />
2828
</module>
29+
<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
30+
<property name="id" value="toLowerCaseWithoutLocale"/>
31+
<property name="format" value="\.toLowerCase\(\)"/>
32+
<property name="maximum" value="0"/>
33+
<property name="message"
34+
value="String.toLowerCase() should be String.toLowerCase(Locale.ROOT) or String.toLowerCase(Locale.ENGLISH)"/>
35+
<property name="ignoreComments" value="true"/>
36+
</module>
37+
<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
38+
<property name="id" value="toUpperCaseWithoutLocale"/>
39+
<property name="format" value="\.toUpperCase\(\)"/>
40+
<property name="maximum" value="0"/>
41+
<property name="message"
42+
value="String.toUpperCase() should be String.toUpperCase(Locale.ROOT) or String.toUpperCase(Locale.ENGLISH)"/>
43+
<property name="ignoreComments" value="true"/>
44+
</module>
2945
</module>
3046
</module>

Diff for: odm/src/main/java/org/springframework/ldap/odm/tools/SchemaReader.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.ldap.odm.tools;
1818

1919
import java.util.HashSet;
20+
import java.util.Locale;
2021
import java.util.Set;
2122

2223
import javax.naming.NamingEnumeration;
@@ -156,7 +157,7 @@ private void createObjectClass(Set<String> objectClasses, DirContext schemaConte
156157
Attribute currentAttribute = valuesEnumeration.nextElement();
157158

158159
// Get the attribute name and lower case it (as this is all case indep)
159-
String currentId = currentAttribute.getID().toUpperCase();
160+
String currentId = currentAttribute.getID().toUpperCase(Locale.ROOT);
160161

161162
// Is this a MUST, MAY or SUP attribute
162163
SchemaAttributeType type = getSchemaAttributeType(currentId);
@@ -168,7 +169,7 @@ private void createObjectClass(Set<String> objectClasses, DirContext schemaConte
168169
switch (type) {
169170
case SUP:
170171
// Its a super class
171-
String lowerCased = currentValue.toLowerCase();
172+
String lowerCased = currentValue.toLowerCase(Locale.ROOT);
172173
if (!schema.getObjectClass().contains(lowerCased)) {
173174
supList.add(lowerCased);
174175
}

Diff for: odm/src/main/java/org/springframework/ldap/odm/tools/SchemaToJava.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.HashMap;
2828
import java.util.HashSet;
2929
import java.util.Hashtable;
30+
import java.util.Locale;
3031
import java.util.Map;
3132
import java.util.Set;
3233
import java.util.regex.Matcher;
@@ -340,7 +341,7 @@ private static Set<String> parseObjectClassesFlag(String objectClassesFlag) {
340341

341342
for (String objectClassFlag : objectClassesFlag.split(",")) {
342343
if (objectClassFlag.length() > 0) {
343-
objectClasses.add(objectClassFlag.toLowerCase().trim());
344+
objectClasses.add(objectClassFlag.toLowerCase(Locale.ROOT).trim());
344345
}
345346
}
346347

Diff for: test/integration-tests-ad/src/test/java/org/springframework/ldap/itest/ad/IncrementalAttributeMapperITests.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.io.UnsupportedEncodingException;
2020
import java.util.List;
21+
import java.util.Locale;
2122

2223
import javax.naming.directory.BasicAttribute;
2324
import javax.naming.directory.DirContext;
@@ -112,7 +113,8 @@ private void createUser(String username) throws UnsupportedEncodingException {
112113
ctx.setAttributeValue("userPrincipalName", username + "@example.com");
113114
ctx.setAttributeValue("cn", username);
114115
ctx.setAttributeValue("description", "Dummy user");
115-
ctx.setAttributeValue("sAMAccountName", username.toUpperCase() + "." + username.toUpperCase());
116+
ctx.setAttributeValue("sAMAccountName",
117+
username.toUpperCase(Locale.ENGLISH) + "." + username.toUpperCase(Locale.ENGLISH));
116118
ctx.setAttributeValue("userAccountControl", "512");
117119

118120
String newQuotedPassword = "\"" + DEFAULT_PASSWORD + "\"";

0 commit comments

Comments
 (0)