...
Many programs only use locale-dependent methods for outputting information, such as dates. Provided that the locale-dependent data is not inspected by the program, and it may safely rely on the default locale.
Noncompliant Code Example (toUpperCase()
)
Many web apps, such as forum or blogging software, input HTML and then display it. Displaying untrusted HTML can subject a web app to XSS (cross-site scripting) or HTML injection vulnerabilities. Therefore, it is vital that HTML be sanitized before sending it to a web browser.
...
Code Block | ||||
---|---|---|---|---|
| ||||
public static void processTag(String tag) { if (tag.toUpperCase().equals("SCRIPT")) { return; } // process tag } |
Compliant Solution (Explicit Locale)
This compliant solution explicitly sets the locale to English to avoid unexpected results.
...
Specifying Locale.ROOT
is a suitable alternative under conditions where an English-specific locale would not be appropriate.
Compliant Solution (Default Locale)
This compliant solution sets the default locale to English before performing string comparisons.
Code Block | ||||
---|---|---|---|---|
| ||||
public static void processTag(String tag) { Locale.setDefault(Locale.ENGLISH); if (tag.toUpperCase().equals("SCRIPT")) { return; } // process tag } |
Compliant Solution (String.equalsIgnoreCase()
)
This compliant solution bypasses locales entirely by performing a case-insensitive match. The String.equalsIgnoreCase()
method creates temporary canonical forms of both strings. This may render them unreadable, but it performs proper comparison without making them dependent on the current locale [Schindler].
Code Block | ||||
---|---|---|---|---|
| ||||
public static void processTag(String tag) { if (tag.equalsIgnoreCase("SCRIPT")) { return; } // process tag } |
Noncompliant Code Example (FileReader
)
Java provides classes for handling input and output which can be based on either bytes or characters. The byte I/O families derive from the InputStream
and OutputStream
interfaces, and are independent of locale or character encoding. However, the character I/O families derive from Reader
and Writer
, and they must convert byte sequences into strings and back. Thus, they rely on a specified character encoding to do their conversion. This encoding is indicated by the file.encoding
system property, which is part of the current locale. Consequently, a file encoded with one encoding, such as UTF-8, must not be read by a character input method using a different encoding, such as UTF-16.
...
Code Block | ||||
---|---|---|---|---|
| ||||
import java.io.*; public class PrintMyself { private static String inputFile = "PrintMyself.java"; private static String outputFile = "PrintMyself.txt"; public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader(new FileReader(inputFile)); PrintWriter writer = new PrintWriter(new FileWriter(outputFile)); int line = 0; while (reader.ready()) { line++; writer.println(line + ": " + reader.readLine()); } reader.close(); writer.close(); } } |
Compliant Solution (Charset
)
In this compliant solution, both the input and output files are explicitly encoded using UTF8. This program behaves correctly regardless of the default encoding.
Code Block | ||||
---|---|---|---|---|
| ||||
public static void main(String[] args) throws IOException { Charset encoding = Charset.forName("UTF8"); BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), encoding)); PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(outputFile), encoding)); int line = 0; /* rest of code unchanged */ |
Noncompliant Code Example (Date
)
While the concepts of days and years are universal, the way in which dates are represented varies across cultures, and are therefore specific to locales. This noncompliant code example examines the current date and prints one of two messages, depending on whether or not the month is June.
...
Code Block |
---|
The date is 20.06.2014 It's not June. |
Compliant Solution (Explicit Locale)
This compliant solution forces the date to be printed in an English format, regardless of the current locale.
Code Block | ||||
---|---|---|---|---|
| ||||
String myString = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US).format(rightNow.getTime()); /* ...rest of code unchanged...*/ |
Compliant Solution (Bypass Locale)
This compliant solution checks the date's MONTH
attribute without formatting it. While date representations vary by culture, the contents of a Calendar
date do not. Consequently, this code works in any locale.
Code Block | ||||
---|---|---|---|---|
| ||||
if (rightNow.get(Calendar.MONTH) == Calendar.JUNE) { /* ...rest of code unchanged...*/ |
Risk Assessment
Failure to specify the appropriate locale when using locale-dependent methods on local-dependent data without specifying the appropriate locale may result in unexpected behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
IDS09-J | medium | probable | medium | P8 | L2 |
Android Implementation Details
A developer can specify locale on Android using java.util.Locale
.
Bibliography
[API 2006] | Class |
[Schindler] | Schindler, Uwe. The Policeman’s Horror: Default Locales, Default Charsets, and Default Timezones, The Generics Policeman Blog |
...