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

fix: AfterQuery using safer right trim to clear FROM clause's joins #7150

Closed
wants to merge 2 commits into from

Conversation

bhowmik-abhijeet
Copy link
Contributor

As a fix to this issue , clearing of db.Statement.Clauses["FROM"] was in introduced in this pull-request

At https://github.com/go-gorm/gorm/blob/master/callbacks/query.go#L291 , it can cause a panic if db.Statement.Clauses["FROM"].Joins slice is being sliced using negative upper bound index. Please observe below the case reproduced in current source code

image

In the case above, wrong column name pets.names (instead of pets.name) is passed as query.
When Count() is called after Find() on the the same gorm.DB instance with a wrong query, it calls AfterQuery twice which in turn tries to trim the slice twice which now is empty after first trim. Hence instead of obtaining actual SQL error, it causes a panic due to index out of bound error.

  • Do only one thing
  • Non breaking API changes
  • Tested

What did this pull request do?

This Pull Request:

  • Safely trims the db.Statement.Clauses["FROM"].Joins
  • Unit test for newly added functions for Safe right trimming of slice
  • Unit Test for wrong query case

User Case Description

User Case:

In one of my our projects, we are using gorm (just fantastic) as ORM support for Postgres. After upgrading gorm version from v1.9.16 -> v1.25.11, we identified panic in API due to broken migration which changes a column name causing the query to be wrong.

Of course this is a minor fix requirement but much needed to prevent API server error and handle SQL error gracefully.

@@ -288,7 +288,7 @@ func AfterQuery(db *gorm.DB) {
// clear the joins after query because preload need it
if v, ok := db.Statement.Clauses["FROM"].Expression.(clause.From); ok {
fromClause := db.Statement.Clauses["FROM"]
fromClause.Expression = clause.From{Tables: v.Tables, Joins: v.Joins[:len(v.Joins)-len(db.Statement.Joins)]} // keep the original From Joins
fromClause.Expression = clause.From{Tables: v.Tables, Joins: utils.RTrimSlice(v.Joins, len(v.Joins)-len(db.Statement.Joins))} // keep the original From Joins
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utils.RTrimSlice makes sure no panic when v.Joins is empty while db.Statement.Joins is not

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant