Copilot commented on code in PR #16312:
URL: https://github.com/apache/grails-core/pull/16312#discussion_r3931682097
##########
grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/finders/DynamicFinder.java:
##########
@@ -767,7 +773,55 @@ private static void resetMethodExpressionPattern() {
methodExpressinPattern = Pattern.compile("\\p{Upper}[\\p{Lower}\\d]+("
+ expressionPattern + ")");
}
+ private static PersistentEntity resolvePersistentEntity(BuildableCriteria
query) {
+ if (query instanceof AbstractCriteriaBuilder) {
+ return ((AbstractCriteriaBuilder) query).getPersistentEntity();
+ }
+ if (query instanceof AbstractDetachedCriteria) {
+ return ((AbstractDetachedCriteria) query).getPersistentEntity();
+ }
+ return null;
+ }
+
+ /**
+ * Rejects sort keys that are not identifier-shaped property paths, and
when a
+ * mapping is available, keys that do not resolve to a persistent property.
+ *
+ * @param entity the entity being queried, or {@code null} when it cannot
be resolved
+ * @param sort the requested sort property
+ */
+ public static void validateSortProperty(PersistentEntity entity, String
sort) {
+ if (sort == null || !SORT_PROPERTY_PATTERN.matcher(sort).matches()) {
+ throw new IllegalArgumentException("Invalid sort property: " +
sort);
+ }
+ if (entity == null) {
+ return;
+ }
+ PersistentEntity current = entity;
+ String[] parts = sort.split("\\.");
+ for (int i = 0; i < parts.length; i++) {
+ PersistentProperty prop = current.getPropertyByName(parts[i]);
+ if (prop == null) {
+ PersistentProperty identity = current.getIdentity();
+ if (identity != null && parts[i].equals(identity.getName()) &&
i == parts.length - 1) {
+ return;
+ }
+ throw new IllegalArgumentException("Unknown sort property: " +
sort);
+ }
+ if (i < parts.length - 1) {
+ if (!(prop instanceof Association)) {
+ throw new IllegalArgumentException("Invalid sort property:
" + sort);
+ }
+ current = ((Association) prop).getAssociatedEntity();
+ if (current == null) {
+ throw new IllegalArgumentException("Invalid sort property:
" + sort);
+ }
+ }
+ }
+ }
+
private static void addSimpleSort(Query q, String sort, String order,
boolean ignoreCase) {
+ validateSortProperty(q.getEntity(), sort);
Review Comment:
This rejects valid sort paths that use a detached-criteria association
alias. For example, `WhereQueryWithAssociationSortSpec.groovy:80-89` creates
the alias `c1` and successfully calls `.list(sort: 'c1.name')`, but
`q.getEntity()` is `Team` (whose mapped properties are only `club`, `name`, and
`players`), so validation now throws `Unknown sort property: c1.name`. Please
resolve recognized query aliases to their mapped associations before validating
the remainder of the path, while retaining the identifier-shape check for
unrecognized input.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]