Affected Version: 2.1.6
If a change in Gerrit contains a file that (only) differs by a removed newline at the file end, displaying the file diff fails with Application Error.
Attached are two files which can be used to reproduce the problem:
a.txt.1: contains 'a' + LF
$ xxd a.txt.1
0000000: 610a
a.txt.2: contains 'a'
$ xxd a.txt.2
0000000: 61
What steps will reproduce the problem?
1. Create a new project in Gerrit:
ssh -p 29418 user@host gerrit create-project --name myProject
2. Clone this project
git clone ssh://user@host:29418/myProject
3. Add the attached file a.txt.1 under the name a.txt, commit and push to Gerrit
git add a.txt
git commit -m "first"
git push ssh://user@host:29418/myProject HEAD:refs/for/master
4. Submit the change in Gerrit
5. Add the attached file a.txt.2 under the name a.txt, commit and push to Gerrit
git add a.txt
git commit -m "second"
git push ssh://user@host:29418/myProject HEAD:refs/for/master
6. Go to the Change in Gerrit and try to open the file diff for a.txt
-> See that it fails with 'Application Error'.
What is the expected output? What do you see instead?
It is expected that the file diff is properly shown and that no Application Error occurs.
Please provide any additional information below.
Here is the stacktrace of the error:
java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 3
at org.eclipse.jgit.util.IntList.get(IntList.java:82)
at org.eclipse.jgit.diff.RawText.getEnd(RawText.java:215)
at org.eclipse.jgit.diff.RawText.getString(RawText.java:187)
at org.eclipse.jgit.diff.RawText.getString(RawText.java:166)
at com.google.gerrit.httpd.rpc.patch.PatchScriptBuilder.packContent(PatchScriptBuilder.java:375)
at com.google.gerrit.httpd.rpc.patch.PatchScriptBuilder.build(PatchScriptBuilder.java:205)
at com.google.gerrit.httpd.rpc.patch.PatchScriptBuilder.toPatchScript(PatchScriptBuilder.java:125)
at com.google.gerrit.httpd.rpc.patch.PatchScriptFactory.call(PatchScriptFactory.java:155)
at com.google.gerrit.httpd.rpc.patch.PatchScriptFactory.call(PatchScriptFactory.java:1)
at com.google.gerrit.httpd.rpc.Handler.to(Handler.java:65)
...
I've had a look at the code and I think the problem is in Gerrit. In
PatchScriptBuilder#packContent(boolean) there is a loop that reads the
context lines before and after the actual diff:
...
for (final EditList.Hunk hunk : list.getHunks()) {
while (hunk.next()) {
if (hunk.isContextLine()) {
final String lineA = a.src.getString(hunk.getCurA());
...
The problem is that in the end it tries to access a non-existing line
(in the example above where a.txt has 1 line, it tries to access the
second line with line index 1), this results then in the
ArrayIndexOutOfBoundsException in JGit.
Maybe the problem could be fixed by checking if the line exists before
accessing it:
if (a.src.size() > hunk.getCurA()) { ...
However then it fails in a later place
(SparseFileContent#apply(SparseFileContent, List<Edit>)) with the same
error...
Mergedinto: 786