TarArchiveEntry(File) now crashes on file system roots
------------------------------------------------------

                 Key: SANDBOX-284
                 URL: https://issues.apache.org/jira/browse/SANDBOX-284
             Project: Commons Sandbox
          Issue Type: Bug
          Components: Compress
    Affects Versions: Nightly Builds
         Environment: win xp sp3, but this is probably irrelevant
            Reporter: Sam Smith
            Priority: Blocker


The TarArchiveEntry(File) constructor now crashes if the File argument is a 
file system root.

For example, on my windows box, I want to backup the entire contents of my F 
drive, so I am supplying a File argument that is constructed as
        new File("F:\\")

That particular file causes the TarArchiveEntry(File) constructor to fail as 
follows:
        Caused by: java.lang.StringIndexOutOfBoundsException: String index out 
of range: -1
                at java.lang.StringBuffer.charAt(StringBuffer.java:162)
                at 
org.apache.commons.compress.archivers.tar.TarArchiveEntry.<init>(TarArchiveEntry.java:245)

Looking at the code (I downloaded revision 743098 yesterday), it is easy to see 
why this occured:

1) the
        if (osname != null) {
logic will strip the "F:" from my path name of "F:\", leaving just the "\"

2) that "\" will then be turned into a single "/" by the 
        fileName = fileName.replace(File.separatorChar, '/');
line

3) that single "/" will then be removed by the
        while (fileName.startsWith("/")) {
logic, leaving the empty string "".

4) then line #245
        if (this.name.charAt(this.name.length() - 1) != '/') {
must crash, because it falsely assumes that fileName has content.

THIS IS A SHOW STOPPER BUG FOR ME.

I am not sure when this current behavior of TarArchiveEntry was introduced; a 
very old codebase (from 2+ years ago) of compress that I used to use handled 
file system roots just fine.

There are many ways to fix this.  For instance, if it is, in fact, OK for the 
name field to be empty, then you can simply put a check on line #245 as follows:
            if ( (name.length() > 0) && (name.charAt(name.length() - 1) != '/') 
) {
(NOTE on coding style: do you really need to use "this." in the constructor 
when there is no possible ambiguity?  Makes your code wordier and therefore 
harder to read.)

My guess, not knowing your full codebase well, is that it is NOT OK for name to 
be blank.  For example, you seem to want directories to end with a '/' char, 
and file ssystem roots are always directories.

Therefore, you have some decisions to make:

a) is it OK for the name field to simply be "/" in the case of file system 
roots?

b) if a) is not good for some reason, then you must introduce an artificial 
root name, so that name takes on a value like
        "filesystemRoot/"
or
        "filesystemRoot_F/"
or whatever.

This bug, by the way, brings up another issue: there currently are no javadocs 
regarding field contracts.  Every field's javadocs needs its constraints to be 
specified as a contract, for example,

    /**
    * The entry's name.
    * <p>
    * Contract: is never null (and never empty?).
    * Contains (only ASCII chars?  any Unicode chars?).
    * Must be (<= 100 chars?  unlimited number of chars?).
    * If {...@link #file} is a directory, then must end in a '/' char.
    * etc...
    */
    private StringBuffer name;


-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to