Pages

Friday, June 27, 2008

Putting the Current Directory in the CLASSPATH

Someone from our users group posed a good question. Should you put the current directory in the CLASSPATH? Does it represent any security issues like on UNIX?

Here is the answer...depends, but it is generally a bad idea. Here is an example. I created a class called TestCase. It calls another class called ClassA in a jar file called ExampleJar.jar. I put another class called ClassA in the current directory and set the CLASSPATH as a passed parameter

java -classpath .:./lib/ExampleJar.jar TestCase
Here are the classes:


1 public class TestCase {
2
3 public TestCase() {
4 }
5
6 public static void main(String[] args) {
7 ClassA a = new ClassA();
8 a.print();
9 }
10 }


1 public class ClassA {
2
3 public void print() {
4 System.out.println("I am ClassA in a jar.");
5 }
6 }


1 public class ClassA {
2
3 // Bad apple!!!
4 public void print() {
5 System.out.println("I am ClassA in the wild...");
6 }
7 }


The question becomes which one of the ClassA files gets called? The legitimate one, or the bad apple?

[sundev:Desktop:root]#java -classpath .:lib/ExampleJar.jar TestCase
I am ClassA in the wild...
If I reverse the order to java -classpath lib/ExampleJar.jar:. TestCase

I get the expected result:

[sundev:Desktop:root]#java -classpath lib/ExampleJar.jar:. TestCase
I am ClassA in a jar.
The Classloader finds the first instance of the class which matches the appropriate signature and loads it. Subsequent classes of the same name and signature are not loaded.

Why does it matter?

The inclusion of the current directory into the CLASSPATH represents a potential security risk, also it may produce unexpected results from similarly named classes. The second item may be a bit more contrived in general terms, i.e. com.abc.ClassA and com.cba.ClassA are called ClassA, but are in different packages. This will not represent a problem.

The security issue can be real. A lot of programs that do installs on Windows specifically, add the CLASSPATH variable to the Windows environment and put the . (period) first. I checked my installation and found it to be the case. I would not knowingly put it there myself. Also I checked a couple of tutorials which suggest that you should do it for convenience. That piece is quickly forgotten 200 pages ago.

ADDENDUM:

Java 6 SE (J6SE) has added some additional enhancements around classpath. You can use the * (asterisk) wildcard to include all files in the classpath:

java -cp "*"; TestCase (Windows)
java -cp '*' TestCase (Unix/OS X)

Mark Reinhold has a blog entry entitled Class-Path Wildcards in Mustang which details it.

4 comments :