Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

500 on CSV diff: runtime error: index out of range #16837

Closed
silverwind opened this issue Aug 27, 2021 · 15 comments · Fixed by #17018
Closed

500 on CSV diff: runtime error: index out of range #16837

silverwind opened this issue Aug 27, 2021 · 15 comments · Fixed by #17018
Assignees
Labels
Milestone

Comments

@silverwind
Copy link
Member

silverwind commented Aug 27, 2021

  • Gitea version (or commit ref): latest 1.15, 0c7927f
  • Git version: 2.33.0
  • Operating system: Ubuntu 20.04

When viewing a certain CSV diff, I see a 500 and this error in the log:

2021/08/27 13:14:14 ...s/context/context.go:195:HTML() [E] Render failed: template: repo/diff/csv_diff:3:15: executing "repo/diff/csv_diff" at <call .root.CreateCsvDiff .file .root.BaseCommit .root.HeadCommit>: error calling call: runtime error: index out of range [-1]

I can't share the particular CSV content but will try to fabricate a file that reproduces that error.

@zeripath
Copy link
Contributor

zeripath commented Sep 4, 2021

It would be helpful if you could upload an example CSV to try.gitea.io.

I think:

diff --git a/templates/repo/diff/csv_diff.tmpl b/templates/repo/diff/csv_diff.tmpl
index b86e9d2a7..b037e29b8 100644
--- a/templates/repo/diff/csv_diff.tmpl
+++ b/templates/repo/diff/csv_diff.tmpl
@@ -12,7 +12,9 @@
 						{{if and (eq $i 0) (eq $j 0)}}
 							<th class="line-num">{{.RowIdx}}</th>
 							{{range $j, $cell := $row.Cells}}
-								{{if eq $cell.Type 2}}
+								{{if not $cell}}
+									<th></th>
+								{{else if eq $cell.Type 2}}
 									<th class="modified"><span class="removed-code">{{.LeftCell}}</span> <span class="added-code">{{.RightCell}}</span></th>
 								{{else if eq $cell.Type 3}}
 									<th class="added"><span class="added-code">{{.LeftCell}}</span></th>
@@ -25,7 +27,9 @@
 						{{else}}
 							<td class="line-num">{{if .RowIdx}}{{.RowIdx}}{{end}}</td>
 							{{range $j, $cell := $row.Cells}}
-								{{if eq $cell.Type 2}}
+								{{if not $cell}}
+									<td></td>
+								{{else if eq $cell.Type 2}}
 									<td class="modified"><span class="removed-code">{{.LeftCell}}</span> <span class="added-code">{{.RightCell}}</span></td>
 								{{else if eq $cell.Type 3}}
 									<td class="added"><span class="added-code">{{.LeftCell}}</span></td>

Would stop the panic but I'm not sure if there is a deeper bug here.

@silverwind
Copy link
Member Author

silverwind commented Sep 6, 2021

Here you go:

https://try.gitea.io/silverwind/symlink-test/commit/46c2ca254f58499afea56cbd16912c3523cc8f00
silverwind/symlink-test@46c2ca2

Essentially, it is a CSV where column names and content have changed:

diff --git a/test.csv b/test.csv
index bfde6bf..ae961ff 100644
--- a/test.csv
+++ b/test.csv
@@ -1,2 +1,2 @@
-a,b,c
-1,2,3
+d,e,f
+4,5,6

Just changing column names alone also triggers it:

https://try.gitea.io/silverwind/symlink-test/commit/653094402e4af6fa3814dc83f9708bc299acae94

diff --git a/test.csv b/test.csv
index ae961ff..f68e6c8 100644
--- a/test.csv
+++ b/test.csv
@@ -1,2 +1,2 @@
-d,e,f
+g,h,i
 4,5,6

@lunny lunny added this to the 1.15.3 milestone Sep 7, 2021
@richmahn
Copy link
Contributor

Is anyone working on this one? Having got quite familiar with the CSV module I'll look.

@richmahn richmahn self-assigned this Sep 10, 2021
@richmahn
Copy link
Contributor

richmahn commented Sep 10, 2021

Maybe what @zeripath wrote above will make it work, but the error one gets from switching the column name is:

An error has occurred:

template: repo/diff/csv_diff:15:21: executing "repo/diff/csv_diff" at <$cell.Type>: nil pointer evaluating *gitdiff.TableDiffCell.Type

@richmahn
Copy link
Contributor

Yes, what @zeripath wrote above removes the error, but then you don't see what it was changed FROM....I assume we need to show two header rows or something to see the change.

@zeripath
Copy link
Contributor

I suspect the diff may need a close looking at.

@silverwind
Copy link
Member Author

Just did a test with the patch above, did not help, still failing with the same error.

@zeripath
Copy link
Contributor

@silverwind can you chat to me on discord - it might be easiest to just give me a copy of the problematic CSVs in question privately so we can just get this sorted.

@KN4CK3R do you have any ideas?

@silverwind
Copy link
Member Author

silverwind commented Sep 11, 2021

@zeripath did you see #16837 (comment)?

File is also on try: https://try.gitea.io/silverwind/symlink-test/src/branch/master/test.csv.

Essentially I think the csv diff crashes when any column names change.

@richmahn
Copy link
Contributor

richmahn commented Sep 11, 2021

Easy to reproduce. Just make a test.csv file like:

a, b, c
1, 2, 3

Then edit again and change it to

d, b, c
1, 2, 3

and then view the commit. It will be 500 error:

image

Using the #16837 (comment) patch works, but does NOT give you the right diff info o know what is going on.... a PR would just tell you a column is being added, but not what was deleted. You are just shown this:

image

Where it is just showing a column has been added and a blank column that means nothing, but what about what the text used to be? It's fine to show a column being added, but we should also show the column that was deleted, such as (I edited the HTML to mock up this):

image

So I'm looking into how to best convey this in the row diff data that the template gets.

@richmahn
Copy link
Contributor

So yeah, I'm stepping through the diff and how the Row/Cell array is populated. It should't be giving a nil entry, but an entry that shows a deleted column and its text, just as if you changed the original CSV above to:

a, a1, b
1, 1a, 2

@richmahn
Copy link
Contributor

Actually it crashes with that too....yet I did get it to work with the real code where you delete one column and add another, but I think there had to be maybe a few columns in-between.

@richmahn
Copy link
Contributor

richmahn commented Sep 11, 2021

Found the bug:

cells[i] = &TableDiffCell{LeftCell: row[i], Type: celltype}

cells[i] = &TableDiffCell{LeftCell: bcell, Type: TableDiffCellAdd}

Going through the unmapped b row (the new content) clobbers the old content's "cells" entries. The cells should be shifted right and then this unmapped b cell can be inserted. Making fix.

@richmahn
Copy link
Contributor

@zeripath @silverwind and anyone else: for review ^^^ #17018

@lunny lunny modified the milestones: 1.15.3, 1.15.4 Sep 24, 2021
@techknowlogick techknowlogick modified the milestones: 1.15.4, 1.15.5 Oct 8, 2021
@richmahn
Copy link
Contributor

richmahn commented Oct 19, 2021

@silverwind @zeripath I finally got back to work on this issue, with my total rework of the diffing of CSV files and even showing when a column is moved. I have pushed my latest changes including test fixes. #17018

zeripath pushed a commit that referenced this issue Oct 20, 2021
Fixes #16837 if a column is deleted.

We were clobbering the columns that were added by looping through the aline (base) and then when bline (head) was looped through, it clobbered what was in the "cells" array that is show in the diff, and then left a nil cell because nothing was shifted.

This fix properly shifts the cells, and properly puts the b cell either at its location or after, according to what the aline placed in the cells.

This includes test, adding a new test function since adding/removing cells works best with three columns, not two, which results in 4 columns of the resulting cells because it has a deleted column and an added column. If you try this locally, you can try those cases and others, such as adding a column.

There was no need to do anything special for the rows when `aline == 0 || bline == 0` so that was removed. This allows the same code to be used for removed or added lines, with the bcell text always being the RightCell, acell text being the LeftCell.

I still added the patch zeripath gave at #16837 (comment) so that just in case for some reason a cell is nil (which shouldn't happen now) it doesn't throw a 500 error, so the user can at least view the raw diff.

Also fixes in the [view.go](https://github.com/go-gitea/gitea/pull/17018/files#diff-43a7f4747c7ba8bff888c9be11affaafd595fd55d27f3333840eb19df9fad393L521) file how if a CSV file is empty (either created empty or if you edit it and remove all contents) it throws a huge 500 error when you then save it (when you view the file). Since we allow creating, saving and pushing empty files, we shouldn't throw an error on an empty CSV file, but just show its empty contents. This doesn't happen if it is a Markdown file or other type of file that is empty.
EDIT: Now handled in the markup/csv renderer code
richmahn added a commit to richmahn/gitea that referenced this issue Oct 20, 2021
6543 pushed a commit that referenced this issue Oct 20, 2021
Chianina pushed a commit to Chianina/gitea that referenced this issue Mar 28, 2022
Fixes go-gitea#16837 if a column is deleted.

We were clobbering the columns that were added by looping through the aline (base) and then when bline (head) was looped through, it clobbered what was in the "cells" array that is show in the diff, and then left a nil cell because nothing was shifted.

This fix properly shifts the cells, and properly puts the b cell either at its location or after, according to what the aline placed in the cells.

This includes test, adding a new test function since adding/removing cells works best with three columns, not two, which results in 4 columns of the resulting cells because it has a deleted column and an added column. If you try this locally, you can try those cases and others, such as adding a column.

There was no need to do anything special for the rows when `aline == 0 || bline == 0` so that was removed. This allows the same code to be used for removed or added lines, with the bcell text always being the RightCell, acell text being the LeftCell.

I still added the patch zeripath gave at go-gitea#16837 (comment) so that just in case for some reason a cell is nil (which shouldn't happen now) it doesn't throw a 500 error, so the user can at least view the raw diff.

Also fixes in the [view.go](https://github.com/go-gitea/gitea/pull/17018/files#diff-43a7f4747c7ba8bff888c9be11affaafd595fd55d27f3333840eb19df9fad393L521) file how if a CSV file is empty (either created empty or if you edit it and remove all contents) it throws a huge 500 error when you then save it (when you view the file). Since we allow creating, saving and pushing empty files, we shouldn't throw an error on an empty CSV file, but just show its empty contents. This doesn't happen if it is a Markdown file or other type of file that is empty.
EDIT: Now handled in the markup/csv renderer code
@go-gitea go-gitea locked and limited conversation to collaborators Apr 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants