Prevent adding nil label to .AddedLabels or .RemovedLabels (#14623)

* Prevent adding nil label to .AddedLabels or .RemovedLabels

There are possibly a few old databases out there with malmigrated data that can
cause panics with empty labels being migrated.

This PR adds a few tests to prevent nil labels being added.

Fix #14466

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Add doctor command to remove the broken label comments

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
zeripath 2021-02-10 02:50:44 +00:00 committed by GitHub
parent 30f7ddb833
commit f82b1dd7c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 5 deletions

View File

@ -305,3 +305,13 @@ func CountWrongUserType() (int64, error) {
func FixWrongUserType() (int64, error) { func FixWrongUserType() (int64, error) {
return x.Where(builder.Eq{"type": 0}.And(builder.Neq{"num_teams": 0})).Cols("type").NoAutoTime().Update(&User{Type: 1}) return x.Where(builder.Eq{"type": 0}.And(builder.Neq{"num_teams": 0})).Cols("type").NoAutoTime().Update(&User{Type: 1})
} }
// CountCommentTypeLabelWithEmptyLabel count label comments with empty label
func CountCommentTypeLabelWithEmptyLabel() (int64, error) {
return x.Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Count(new(Comment))
}
// FixCommentTypeLabelWithEmptyLabel count label comments with empty label
func FixCommentTypeLabelWithEmptyLabel() (int64, error) {
return x.Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Delete(new(Comment))
}

View File

@ -111,6 +111,24 @@ func checkDBConsistency(logger log.Logger, autofix bool) error {
} }
} }
// find label comments with empty labels
count, err = models.CountCommentTypeLabelWithEmptyLabel()
if err != nil {
logger.Critical("Error: %v whilst counting label comments with empty labels")
return err
}
if count > 0 {
if autofix {
updatedCount, err := models.FixCommentTypeLabelWithEmptyLabel()
if err != nil {
logger.Critical("Error: %v whilst removing label comments with empty labels")
return err
}
logger.Info("%d label comments with empty labels removed", updatedCount)
} else {
logger.Warn("%d label comments with empty labels", count)
}
}
// TODO: function to recalc all counters // TODO: function to recalc all counters
return nil return nil

View File

@ -371,6 +371,10 @@ func NewFuncMap() []template.FuncMap {
"RenderLabels": func(labels []*models.Label) template.HTML { "RenderLabels": func(labels []*models.Label) template.HTML {
html := `<span class="labels-list">` html := `<span class="labels-list">`
for _, label := range labels { for _, label := range labels {
// Protect against nil value in labels - shouldn't happen but would cause a panic if so
if label == nil {
continue
}
html += fmt.Sprintf("<div class='ui label' style='color: %s; background-color: %s'>%s</div> ", html += fmt.Sprintf("<div class='ui label' style='color: %s; background-color: %s'>%s</div> ",
label.ForegroundColor(), label.Color, RenderEmoji(label.Name)) label.ForegroundColor(), label.Color, RenderEmoji(label.Name))
} }

View File

@ -2464,7 +2464,7 @@ func combineLabelComments(issue *models.Issue) {
if i == 0 || cur.Type != models.CommentTypeLabel || if i == 0 || cur.Type != models.CommentTypeLabel ||
(prev != nil && prev.PosterID != cur.PosterID) || (prev != nil && prev.PosterID != cur.PosterID) ||
(prev != nil && cur.CreatedUnix-prev.CreatedUnix >= 60) { (prev != nil && cur.CreatedUnix-prev.CreatedUnix >= 60) {
if cur.Type == models.CommentTypeLabel { if cur.Type == models.CommentTypeLabel && cur.Label != nil {
if cur.Content != "1" { if cur.Content != "1" {
cur.RemovedLabels = append(cur.RemovedLabels, cur.Label) cur.RemovedLabels = append(cur.RemovedLabels, cur.Label)
} else { } else {
@ -2474,11 +2474,13 @@ func combineLabelComments(issue *models.Issue) {
continue continue
} }
if cur.Label != nil {
if cur.Content != "1" { if cur.Content != "1" {
prev.RemovedLabels = append(prev.RemovedLabels, cur.Label) prev.RemovedLabels = append(prev.RemovedLabels, cur.Label)
} else { } else {
prev.AddedLabels = append(prev.AddedLabels, cur.Label) prev.AddedLabels = append(prev.AddedLabels, cur.Label)
} }
}
prev.CreatedUnix = cur.CreatedUnix prev.CreatedUnix = cur.CreatedUnix
issue.Comments = append(issue.Comments[:i], issue.Comments[i+1:]...) issue.Comments = append(issue.Comments[:i], issue.Comments[i+1:]...)
i-- i--