Is this an off-by-one bug in Java 7?
Asked Answered
G

2

10

I don't know where to seek clarifications and confirmations on Java API documentation and Java code, so I'm doing it here.

In the API documentation for FileChannel, I'm finding off-by-one errors w.r.t. to file position and file size in more places than one.

Here's just one example. The API documenation for transferFrom(...) states:

"If the given position is greater than the file's current size then no bytes are transferred."

I confirmed that the OpenJDK code too contains this code...

public long transferFrom(ReadableByteChannel src, long position, long count)
    throws IOException
{
    // ...
    if (position > size())
        return 0;
    // ...
}

... in file FileChannelImpl.java consistent with the documentation.

Now, while the above code snippet and the API documentation appear mutually consistent, I 'feel' that the above should be 'greater than or equal to' and not merely 'greater than' because position being a 0-based index into the file's data, reading at position == size() will have no data to return to the caller! (At position == size() - 1, at least 1 byte -- the last byte of the file -- could be returned to the caller.)

Here are some other similar instances in the same API documentation page:

  1. position(...): "Setting the position to a value that is greater than the file's current size is legal but does not change the size of the file." (Should have been 'greater than or equal to'.)

  2. transferTo(...): " If the given position is greater than the file's current size then no bytes are transferred." (Should have been 'greater than or equal to'.)

  3. read(...): "If the given position is greater than the file's current size then no bytes are read." (Should have been 'greater than or equal to'.)

Lastly, the documentation section for the return value of read(...) fails to remain even self-consistent with the rest of the documentation. Here's what it states:

read(...)

Returns:

The number of bytes read, possibly zero, or -1 if the given position is greater than or equal to the file's current size

So, in this lone instance, I do see them mention the right thing.

Overall, I don't know what to make of all of this. If I write my code today matching this documentation, then a future bug fix in Java (code or documentation) will render my code buggy, requiring a fix from my side as well. If I do the right thing myself today with things as they stand today, then my code becomes buggy to start with!

Grammer answered 1/12, 2013 at 5:48 Comment(3)
My advice would be to run a few experiments and file a bug report: bugreport.sun.com/bugreportLeucopenia
I filed another bug there ~2 weeks back. Got a confirmation and a bug ID from the daemon that my bug got accepted, however... I cannot lookup this bug ID and its current status in the bug database even today. So, not sure, what these folks are doing with the bugs filed.Grammer
My impression from reading bug reports is they are a bit slow (because they get a lot of them) but they do get to them if the report is clear. If a real problem arose from the issue you've raised it seems like a bug they would get to considering all fixing it would entail is changing some operators.Leucopenia
G
2

This could be a bit clearer in the javadoc and is now tracked here:

https://bugs.openjdk.java.net/browse/JDK-8029370

Note that clarifying the javadoc shouldn't change anything for implementations of FileChannel (for example, the transfer methods return the number of bytes transferred so this is 0 when the position is at size or beyond size).

Greenberg answered 1/12, 2013 at 11:23 Comment(0)
F
2

It is not an off-by-one bug in that there is no behavior problem right? At best a doc problem. The docs aren't wrong here maybe just not complete.

However I am not sure they are missing something. position == size() is not an exceptional situation. It is a situation where 0 bytes can be read kind of by definition. position > size() is exceptional: less than 0 bytes can be read. It needs a note. Does an exception throw? Or nothing. read() is different since it has to return a byte so having 0 to read is the exceptional condition too.

I personally think the fact that you're asking means the docs could be more explicit. It is also not clear why that method doesnt short circuit rather than try to transfer 0 bytes. But there looks like a possible logic behind it.

(Or do you mean it does something not documented?)

Ferromagnesian answered 1/12, 2013 at 6:10 Comment(4)
Sean, not satisfied with your answer. I'm trying to write a full fledged custom filesystem using the FileSystemProvider SPI of Java 7, so I need to know very precisely what semantics I am to provide to keep current and future releases of Java happy with my code. [contd...]Grammer
I'm seeing this as a problem both with the documentation and the code. If the code had >= in it, it would have been just a documentation bug and I could trusted my built-in instinct about position and size handling. But given that even the documentation is not fully self-consistent in all places, I'm now really confused on what logic to write that will work today and tomorrow with future releases/patches of Java. I'll have to actively track these releases and forbid my customers NOT to apply this or that release patch of Java, which kinda sucks.Grammer
It seems more like a doc problem to me, for example transferFrom says no bytes are read if the position is > size but if position == size then no bytes should be transferred as well. Hence why I'd just suggest the OP see if it can be broken and if so file a bug report.Leucopenia
@Grammer I am not writing the software or docs for you, or claiming they are correct or consistent. Just trying to help parse what you are reading. But, what behavior is ambiguous? it seems like the behavior is fully specified even in the position == size() case just not by the sentences you bold-face, and even though it'd be nice if they did.Ferromagnesian
G
2

This could be a bit clearer in the javadoc and is now tracked here:

https://bugs.openjdk.java.net/browse/JDK-8029370

Note that clarifying the javadoc shouldn't change anything for implementations of FileChannel (for example, the transfer methods return the number of bytes transferred so this is 0 when the position is at size or beyond size).

Greenberg answered 1/12, 2013 at 11:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.