fix: replace null char with space for issue/comment content (#40014) (#40034)

A simple workaround to fix
https://github.com/go-gitea/gitea/issues/40003

Backport of https://github.com/go-gitea/gitea/pull/40014
This commit is contained in:
wxiaoguang authored and GitHub committed 2026-10-27 03:14:59 +08:00
1 parent 1b8a7c4d85
commit 79189a959f
3 files changed
+46

No files matched your search

+10
View File
@@ -34,6 +34,7 @@ import (
"gitea.dev/modules/util"
"xorm.io/builder"
"xorm.io/xorm"
)
// ErrCommentNotExist represents a "CommentNotExist" kind of error.
@@ -369,12 +370,19 @@ func (c *Comment) LoadIssue(ctx context.Context) (err error) {
return err
}
var (
_ xorm.BeforeInsertProcessor = (*Comment)(nil)
_ xorm.BeforeUpdateProcessor = (*Comment)(nil)
)
// BeforeInsert will be invoked by XORM before inserting a record
func (c *Comment) BeforeInsert() {
c.PatchQuoted = c.Patch
if !utf8.ValidString(c.Patch) {
c.PatchQuoted = strconv.Quote(c.Patch)
}
sanitizeDatabaseStringContent(&c.Content)
}
// BeforeUpdate will be invoked by XORM before updating a record
@@ -383,6 +391,8 @@ func (c *Comment) BeforeUpdate() {
if !utf8.ValidString(c.Patch) {
c.PatchQuoted = strconv.Quote(c.Patch)
}
sanitizeDatabaseStringContent(&c.Content)
}
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
+23
View File
@@ -11,6 +11,7 @@ import (
"regexp"
"slices"
"strconv"
"strings"
"gitea.dev/models/db"
project_model "gitea.dev/models/project"
@@ -25,6 +26,7 @@ import (
"gitea.dev/modules/util"
"xorm.io/builder"
"xorm.io/xorm"
)
// ErrIssueNotExist represents a "IssueNotExist" kind of error.
@@ -123,6 +125,27 @@ func init() {
db.RegisterModel(new(IssueIndex))
}
func sanitizeDatabaseStringContent(s *string) {
// postgresql doesn't like "\x00"
// this is only a simple workaround for issues like https://github.com/go-gitea/gitea/issues/28890 and https://github.com/go-gitea/gitea/issues/40003
*s = strings.ReplaceAll(*s, "\x00", " ")
}
var (
_ xorm.BeforeInsertProcessor = (*Issue)(nil)
_ xorm.BeforeUpdateProcessor = (*Issue)(nil)
)
func (issue *Issue) BeforeInsert() {
sanitizeDatabaseStringContent(&issue.Title)
sanitizeDatabaseStringContent(&issue.Content)
}
func (issue *Issue) BeforeUpdate() {
sanitizeDatabaseStringContent(&issue.Title)
sanitizeDatabaseStringContent(&issue.Content)
}
// LoadTotalTimes load total tracked time
func (issue *Issue) LoadTotalTimes(ctx context.Context) (err error) {
opts := FindTrackedTimesOptions{IssueID: issue.ID}
+13
View File
@@ -29,6 +29,7 @@ import (
"github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func getIssuesSelection(t testing.TB, htmlDoc *HTMLDoc) *goquery.Selection {
@@ -780,3 +781,15 @@ func TestIssueReferenceURL(t *testing.T) {
ref, _ = htmlDoc.Find(`.timeline-item.comment:not(.issue-content-comment) .reference-issue`).Attr("data-reference")
assert.Equal(t, setting.AppURL+"user2/repo1/issues/1#issuecomment-2", ref)
}
func TestIssueCommentContent(t *testing.T) {
defer tests.PrepareTestEnv(t)()
issue := &issues_model.Issue{Title: "title\x00content", Content: "body\x00content"}
require.NoError(t, db.Insert(t.Context(), issue))
unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issue.ID, Title: "title content", Content: "body content"})
comment := &issues_model.Comment{Content: "body\x00content"}
require.NoError(t, db.Insert(t.Context(), comment))
unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: comment.ID, Content: "body content"})
}